Replace the built-in min functions in python - python

I should write a function min_in_list(munbers), which takes a list of
numbers and returns the smallest one. NOTE: built-in function min is NOT allowed!
def min_in_list(numbers):
the_smallest = [n for n in numbers if n < n+1]
return the_smallest
What's wrong?

def min_of_two(x, y):
if x >= y: return x
else: return y
def min_in_list(numbers):
return reduce(min_of_two, numbers)
You have to produce 1 number from list, not just another list. And this is work for reduce function (of course, you can implement it without reduce, but by analogy with it).

Here you go. This is almost certainly about as simple as you could make it. You don't even have to give me credit when you turn the assignment in.
import itertools
import functools
import operator
def min(seq, keyfun=operator.gt):
lt = lambda n: functools.partial(keyfun, n)
for i in seq:
lti = lt(i)
try:
next(itertools.ifilter(lti, seq))
except:
return i

min = lambda n: return reduce(lambda x,y: (x>y) and return x or return y,n)
Never been tested, use at your own risk.

Related

calculating current value based on previous value

i would like to perform a calculation using python, where the current value (i) of the equation is based on the previous value of the equation (i-1), which is really easy to do in a spreadsheet but i would rather learn to code it
i have noticed that there is loads of information on finding the previous value from a list, but i don't have a list i need to create it! my equation is shown below.
h=(2*b)-h[i-1]
can anyone give me tell me a method to do this ?
i tried this sort of thing, but that will not work as when i try to do the equation i'm calling a value i haven't created yet, if i set h=0 then i get an error that i am out of index range
i = 1
for i in range(1, len(b)):
h=[]
h=(2*b)-h[i-1]
x+=1
h = [b[0]]
for val in b[1:]:
h.append(2 * val - h[-1]) # As you add to h, you keep up with its tail
for large b list (brr, one-letter identifier), to avoid creating large slice
from itertools import islice # For big list it will keep code less wasteful
for val in islice(b, 1, None):
....
As pointed out by #pad, you simply need to handle the base case of receiving the first sample.
However, your equation makes no use of i other than to retrieve the previous result. It's looking more like a running filter than something which needs to maintain a list of past values (with an array which might never stop growing).
If that is the case, and you only ever want the most recent value,then you might want to go with a generator instead.
def gen():
def eqn(b):
eqn.h = 2*b - eqn.h
return eqn.h
eqn.h = 0
return eqn
And then use thus
>>> f = gen()
>>> f(2)
4
>>> f(3)
2
>>> f(2)
0
>>>
The same effect could be acheived with a true generator using yield and send.
First of, do you need all the intermediate values? That is, do you want a list h from 0 to i? Or do you just want h[i]?
If you just need the i-th value you could us recursion:
def get_h(i):
if i>0:
return (2*b) - get_h(i-1)
else:
return h_0
But be aware that this will not work for large i, as it will exceed the maximum recursion depth. (Thanks for pointing this out kdopen) In that case a simple for-loop or a generator is better.
Even better is to use a (mathematically) closed form of the equation (for your example that is possible, it might not be in other cases):
def get_h(i):
if i%2 == 0:
return h_0
else:
return (2*b)-h_0
In both cases h_0 is the initial value that you start out with.
h = []
for i in range(len(b)):
if i>0:
h.append(2*b - h[i-1])
else:
# handle i=0 case here
You are successively applying a function (equation) to the result of a previous application of that function - the process needs a seed to start it. Your result looks like this [seed, f(seed), f(f(seed)), f(f(f(seed)), ...]. This concept is function composition. You can create a generalized function that will do this for any sequence of functions, in Python functions are first class objects and can be passed around just like any other object. If you need to preserve the intermediate results use a generator.
def composition(functions, x):
""" yields f(x), f(f(x)), f(f(f(x)) ....
for each f in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
yield x
Your specs require a seed and a constant,
seed = 0
b = 10
The equation/function,
def f(x, b = b):
return 2*b - x
f is applied b times.
functions = [f]*b
Usage
print list(composition(functions, seed))
If the intermediate results are not needed composition can be redefined as
def composition(functions, x):
""" Returns f(x), g(f(x)), h(g(f(x)) ....
for each function in functions
functions is an iterable of callables taking one argument
"""
for f in functions:
x = f(x)
return x
print composition(functions, seed)
Or more generally, with no limitations on call signature:
def compose(funcs):
'''Return a callable composed of successive application of functions
funcs is an iterable producing callables
for [f, g, h] returns f(g(h(*args, **kwargs)))
'''
def outer(f, g):
def inner(*args, **kwargs):
return f(g(*args, **kwargs))
return inner
return reduce(outer, funcs)
def plus2(x):
return x + 2
def times2(x):
return x * 2
def mod16(x):
return x % 16
funcs = (mod16, plus2, times2)
eq = compose(funcs) # mod16(plus2(times2(x)))
print eq(15)
While the process definition appears to be recursive, I resisted the temptation so I could stay out of maximum recursion depth hades.
I got curious, searched SO for function composition and, of course, there are numerous relavent Q&A's.

Using Reduce Function in Python To Find Factorial

Hi I'm trying to write a function to find the factorial product of any given number. For example for factorial (6) I would get the product of 6*5*3*2*1.
so for factorial(3) the output would be 6.
The functions I have so far are:
import functools
def mult(x, y):
return x * y
def factorial(n):
if n == 0:
return 1
else:
functools.reduce(mult(n,factorial(n - 1)))
But I keep getting an error that Python is expecting 2 arguments and 1 is given. I know I have to use range somehow but I can't figure it out. How do I edit my existing code so that it runs properly?
you can do this pretty easily:
>>> import functools, operator
>>> functools.reduce(operator.mul, xrange(1, 6))
120
Note that the first argument is a function (you're passing the result of a function call). the second argument is an iterable. Also note that written this way, no recursion is needed...
operator.mul is equivalent to your mult function
import functools
def factorial(n):
if n == 0:
return 1
else:
return functools.reduce(lambda x,y: x*y, range(1,n+1))
print factorial(3)
Of course you can use you own multi function instead of the lambda if you prefer.
>>> x = 8
>>> reduce(lambda x,y: x*y, [1, 1] if x == 0 else xrange(1, x+1))
n = int(input())
import functools
def factorial(n):
if n == 0:
return 1
else:
return functools.reduce(lambda x,y: x*y , range(1,n+1))
print(factorial(n))
output:-
Input
3
Solution output
6
If you are using 2.7, then I would reccomend looking here at the documentation for reduce. If you are using 3, then we see that
functools.reduce is the same as 2.7's reduce
That is, we see that we need to call functools in the same way as in 2.7. The following is a representation of that:
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
, which translates to:
functools.reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
For the case of your example, you are making your own operator, which is confusing reduce. This can be solved by adding import operator , and then using the methods that are declared that are defined in operator (i.e. operator.add).
I hope this helps clear things up!
from functools import reduce
f=lambda x,y:x*y
def factorial(number):
if(number==1):
return 1
else:
return reduce(f,range(1,number+1))
print(factorial(n))
Here is a perfect snippet for the factorial function using a reduce built-in function. This will print 1 when n=0, as the factorial of 0 is 1.
# Read the input as an integer
n = 4
# Import the reduce() function
from functools import reduce
fact = lambda x,y:x*y
print(1 if n == 0 else reduce(fact,range(1,n+1)))
My solution:
from functools import reduce
list_num = list(range(1,8,1)) # instead of 8 put the number+1 of which you need factorial
def fact_num(acc, item):
return acc*item
print(reduce(fact_num, list_num,1))
from functools import reduce
n = int(input("Enter a number: "))
print("Factorial is:", reduce(lambda x, y: x*y, range(1, n+1)))
n = int (input ("Enter a natural number "))
n_list = range(1,n+1)
from functools import reduce
factorial = reduce(lambda x,y: x*y, n_list) factorial
-----Import the reduce() function
from functools import reduce
---Read the input as an integer
n = int(input())
fact=reduce(lambda x,y:x+y,range(n+1))
print(fact)

Python: A better way to write n compositions of a function?

I wrote a function "rep" that takes a function f and takes n compositions of f.
So rep(square,3) behaves like this: square(square(square(x))).
And when I pass 3 into it, rep(square,3)(3)=6561.
There is no problem with my code, but I was wondering if there was a way to make it "prettier" (or shorter) without having to call another function or import anything. Thanks!
def compose1(f, g):
"""Return a function h, such that h(x) = f(g(x))."""
def h(x):
return f(g(x))
return h
def rep(f,n):
newfunc = f
count=1
while count < n:
newfunc = compose1(f,newfunc)
count+=1
return newfunc
If you're looking for speed, the for loop is clearly the way to go. But if you're looking for theoretical academic acceptance ;-), stick to terse functional idioms. Like:
def rep(f, n):
return f if n == 1 else lambda x: f(rep(f, n-1)(x))
def rep(f, n):
def repeated(x):
for i in xrange(n):
x = f(x)
return x
return repeated
Using a for loop instead of while is shorter and more readable, and compose1 doesn't really need to be a separate function.
While I agree that repeated composition of the same function is best done with a loop, you could use *args to compose an arbitrary number of functions:
def identity(x):
return x
def compose(*funcs):
if funcs:
rest = compose(*funcs[1:])
return lambda x: funcs[0](rest(x))
else:
return identity
And in this case you would have:
def rep(f,n):
funcs = (f,)*n # tuple with f repeated n times
return compose(*funcs)
And as DSM kindly pointed out in the comments, you could remove the recursion like so:
def compose(*funcs):
if not funcs:
return identity
else:
def composed(x):
for f in reversed(funcs):
x = f(x)
return x
return composed
(also note that you can replace x with *args if you also want to support arbitrary arguments to the functions you're composing, but I left it at one argument since that's how you have it in the original problem)
Maybe someone will find this solution useful
Compose number of functions
from functools import reduce
def compose(*functions):
return reduce(lambda x, y: (lambda arg: x(y(arg))), functions)
Use list comprehensions to generate list of functions
def multi(how_many, func):
return compose(*[func for num in range(how_many)])
Usage
def square(x):
return x * x
multi(3, square)(3) == 6561

Elegant way to calculate first generator result larger than X

I have a generator and would like to find out what the first value which it generates larger than X. One way to do this is as follows, but it seems rather long-winded (it reads like it repeats itself).
def long_winded(gen,X)
n = next(gen)
while n < X: n=next(gen)
return n
What I wanted to write was something more simply:
short_broken(gen,X):
while next(gen)<X: pass
return next(gen) # returns the SECOND value larger than X, as gen is called again
short_broken2(gen,X):
while n = next(gen)<X: pass # Not python syntax!
return n
Is there a pythonically-concise way to return the same result?
from itertools import dropwhile
def first_result_larger_than_x(gen, X):
return next(dropwhile(lambda n: n <= X, gen))
Note that your code examples from the OP are actually returning the first result greater than or equal to X. I've corrected that in this code example, but if that was what you actually wanted, change the <= to a <.
def short2(gen,X):
for x in gen:
if x > X:
return x
or as a 1-liner (which I prefer to the itertools variant):
def short3(gen,X):
return next(x for x in gen if x > X)
my original answer -- left only for the sake of posterity
I'm not necessarily asserting that this method is better, but you can use a recursive function:
def short(gen,X):
n = next(gen)
return n if n>X else short(gen,X)

How to repeat a function n times

I'm trying to write a function in python that is like:
def repeated(f, n):
...
where f is a function that takes one argument and n is a positive integer.
For example if I defined square as:
def square(x):
return x * x
and I called
repeated(square, 2)(3)
this would square 3, 2 times.
That should do it:
def repeated(f, n):
def rfun(p):
return reduce(lambda x, _: f(x), xrange(n), p)
return rfun
def square(x):
print "square(%d)" % x
return x * x
print repeated(square, 5)(3)
output:
square(3)
square(9)
square(81)
square(6561)
square(43046721)
1853020188851841
or lambda-less?
def repeated(f, n):
def rfun(p):
acc = p
for _ in xrange(n):
acc = f(acc)
return acc
return rfun
Using reduce and lamba.
Build a tuple starting with your parameter, followed by all functions you want to call:
>>> path = "/a/b/c/d/e/f"
>>> reduce(lambda val,func: func(val), (path,) + (os.path.dirname,) * 3)
"/a/b/c"
Something like this?
def repeat(f, n):
if n==0:
return (lambda x: x)
return (lambda x: f (repeat(f, n-1)(x)))
Use an itertools recipe called repeatfunc that performs this operation.
Given
def square(x):
"""Return the square of a value."""
return x * x
Code
From itertools recipes:
def repeatfunc(func, times=None, *args):
"""Repeat calls to func with specified arguments.
Example: repeatfunc(random.random)
"""
if times is None:
return starmap(func, repeat(args))
return starmap(func, repeat(args, times))
Demo
Optional: You can use a third-party library, more_itertools, that conveniently implements these recipes:
import more_itertools as mit
list(mit.repeatfunc(square, 2, 3))
# [9, 9]
Install via > pip install more_itertools
Using reduce and itertools.repeat (as Marcin suggested):
from itertools import repeat
from functools import reduce # necessary for python3
def repeated(func, n):
def apply(x, f):
return f(x)
def ret(x):
return reduce(apply, repeat(func, n), x)
return ret
You can use it as follows:
>>> repeated(os.path.dirname, 3)('/a/b/c/d/e/f')
'/a/b/c'
>>> repeated(square, 5)(3)
1853020188851841
(after importing os or defining square respectively)
I think you want function composition:
def compose(f, x, n):
if n == 0:
return x
return compose(f, f(x), n - 1)
def square(x):
return pow(x, 2)
y = compose(square, 3, 2)
print y
Here's a recipe using reduce:
def power(f, p, myapply = lambda init, g:g(init)):
ff = (f,)*p # tuple of length p containing only f in each slot
return lambda x:reduce(myapply, ff, x)
def square(x):
return x * x
power(square, 2)(3)
#=> 81
I call this power, because this is literally what the power function does, with composition replacing multiplication.
(f,)*p creates a tuple of length p filled with f in every index. If you wanted to get fancy, you would use a generator to generate such a sequence (see itertools) - but note it would have to be created inside the lambda.
myapply is defined in the parameter list so that it is only created once.

Categories