Print Fibonacci Series using lambda and map or reduce in python - python

I want to print Fibonacci Series using lambda() function with map() or reduce() function in Python.
Note: I did search on SO, but could only find questions related to Printing nth Fibonacci number. e.g Fibonacci numbers, with an one-liner in Python 3?

I have the following working solutions:
A. Using lambda() + reduce():
>>> fib = lambda n: reduce(lambda x, _: x+[x[-1]+x[-2]], range(n-2), [0, 1])
>>> fib(10)
>>> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Note: Not able to use x.append(x[-1]+x[-2]). Gives AttributeError (Don't know why)
B. Using lambda() + map(): (Have to use a variable for result)
>>> result = [0,1]
>>> fib = lambda n: map(lambda _: result.append(result[-1] + result[-2]), xrange(n-2))
>>> fib(10) ## Ignore its output ##
>>> result ## Stores the result ##
>> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Fibonacci using reduce() and lambda()
from functools import reduce
def fibonacci(count):
sequence = (0, 1)
for _ in range(2, count):
sequence += (reduce(lambda a, b: a + b, sequence[-2:]), )
return sequence[:count]
print(fibonacci(10))
OUTPUT
(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
Fibonacci using map() and lambda()
def fibonacci(count):
sequence = [0, 1]
any(map(lambda _: sequence.append(sum(sequence[-2:])), range(2, count)))
return sequence[:count]
print(fibonacci(10))
OUTPUT
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Code Snippet:
fibonacci = lambda number: number if number <= 1 else fibonacci(number - 1) + fibonacci(number - 2);
listOfFibonacciNumbers = list(map(fibonacci, range(0, 20, 1)));
print(listOfFibonacciNumbers);
Output:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
In place of 20, you can give your number.
I hope this helps:)

yo can try this for Fibonacci using reduce() and lambda()
def Fib(count):
first =[0,1]
for i in range(0,count-2):
first.append(reduce(lambda x,y : x+y,first[-2:]))
print(first)
Fib(10)
output
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Here's what might help you!
Implemented using reduce() and lambda
from functools import reduce
fibonacci_seq = [0, 1]
n = 10
reduce(lambda a, b: len(fibonacci_seq) < n and (fibonacci_seq.append(a+b) or a+b), fibonacci_seq)
(fibonacci_seq.append(a+b) or a+b) : as the <any_list>.append(ele) returns None, I'm using it to append the next element in the series to the fibonacci_seq. oring it with a+b allows to return a+b as the result to the reduce() function to operate on it with the next element in the sequence.
len(fibonacci_seq) < n : The list stops growing once the len(list) reaches n.
OUTPUT
print(fibonacci_seq)
>>> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
The above method returns the right sequence for n = 2 onwards.

try this code which prints the first 10 Fibonacci numbers using LAMBDA
fib = lambda n: n if n<=1 else fib(n-1)+fib(n-2)
for i in range(10):print(fib(i))

Related

Python: Create function that iterates through list and returns a copy of list with a number removed

I have the following list:
listInitial = [20, 33, 24, 11, 0, 4, 3, 11]
I'm trying to write a function that iterates through it and returns a copy of this list with 11 removed. Desired output is: [20, 33, 24, 0, 4, 3]
I want to use the append method and for loop in my function. Below is my code:
listSecond = []
def iterateandremove (listInitial, num):
for i in listInitial:
if i != num:
listSecond.append(i)
print (listSecond)
return (listSecond)
iterateandremove (listInitial, 11)
When I run the code it prints the correct list out. But my function doesn't return anything at all. What am I doing wrong?
You should define listSecond in your function and return it from there.
This way if you run it multiple times, you only return your input list and not all the previous ones combined.
def iterateandremove (listInitial, num):
listSecond = []
for i in listInitial:
if i != num:
listSecond.append(i)
return (listSecond)
removed = iterateandremove(listInitial, 11)
print(removed)
#[20, 33, 24, 0, 4, 3]
You could also do this with a simple list comprehension without declaring listSecond
def iterateandremove(initial, num):
return [n for n in initial if n != num]
When I run the code it prints the correct list out. But my function doesn't return anything at all. What am I doing wrong?
That's because you didn't assign it to a variable. You'll also want to create a new container within the function, and not use a global variable. Try this:
def iterate_and_remove(list_initial, num):
list_second = []
for i in list_initial:
if i != num:
list_second.append(i)
return list_second
result = iterate_and_remove([1,2,3,4], 4)
print(result)
You could also do this with a list comprehension:
list_second = [i for i in list_initial if i != 11]
Another alternative;
listInitial = [20, 33, 24, 11, 0, 4, 3, 11]
def iterateandremove(listInitial, num):
return list(filter((num).__ne__, listInitial))
print(iterateandremove(listInitial, 11))
[20, 33, 24, 0, 4, 3]
lambda function also a good candidate for this;
listInitial = [20, 33, 24, 11, 0, 4, 3, 11]
def iterateandremove(listInitial, num):
return list(filter(lambda digit: digit != num, listInitial))
print(iterateandremove(listInitial, 11))
[20, 33, 24, 0, 4, 3]
Everything seems ok and the function is returning the list without 11.
returnedList = iterateandremove (listInitial, 11)
print(returnedList) #[20, 33, 24, 0, 4, 3]
def iterateandremove(listInitial, num):
return [n for n in listInitial if n != num]
listInitial = [20, 33, 24, 11, 0, 4, 3, 11]
print(iterateandremove(listInitial, 11))
If you are using python3, the list comprehension would do the work for you like the code above.
If you are using python2, I would suggest using python3 instead, for more details, see https://www.python.org/doc/sunset-python-2/

Working around evaluation time discrepancy in generators

I found myself running into the gotcha under 'evaluation time discrepancy' from this list today, and am having a hard time working around it.
As a short demonstration of my problem, I make infinite generators that skip every nth number, with n going from [2..5]:
from itertools import count
skip_lists = []
for idx in range(2, 5):
# skip every 2nd, 3rd, 4th.. number
skip_lists.append(x for x in count() if (x % idx) != 0)
# print first 10 numbers of every skip_list
for skip_list in skip_lists:
for _, num in zip(range(10), skip_list):
print("{}, ".format(num), end="")
print()
Expected output:
1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
1, 2, 4, 5, 7, 8, 10, 11, 13, 14,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
Actual output:
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
Once I remembered that great feature, I tried to "solve" it by binding the if clause variable to a constant that would be part of the skip_list:
from itertools import count
skip_lists = []
for idx in range(2, 5):
# bind the skip distance
skip_lists.append([idx])
# same as in the first try, but use bound value instead of 'idx'
skip_lists[-1].append(x for x in count() if (x % skip_lists[-1][0]) != 0)
# print first 10 numbers of every skip_list
for skip_list in (entry[1] for entry in skip_lists):
for _, num in zip(range(10), skip_list):
print("{}, ".format(num), end="")
print()
But again:
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
Apart from an actual solution, I would also love to learn why my hack didn't work.
The value of idx is never looked up until you start iterating on the generators (generators are evaluated lazily), at which point idx = 4 the latest iteratee value, is what is present in the module scope.
You can make each appended generator stateful in idx by passing idx to a function and reading the value from the function scope at each generator's evaluation time. This exploits the fact that the iterable source of a generator expression is evaluated at the gen. exp's creation time, so the function is called at each iteration of the loop, and idx is safely stored away in the function scope:
from itertools import count
skip_lists = []
def skip_count(skip):
return (x for x in count() if (x % skip) != 0)
for idx in range(2, 5):
# skip every 2nd, 3rd, 4th.. number
skip_lists.append(skip_count(idx))
Illustration of generator expression's iterable source evaluation at gen. exp's creation:
>>> (i for i in 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
Your case is a bit trickier since the exclusions are actually done in a filter which is not evaluated at the gen exp's creation time:
>>> (i for i in range(2) if i in 5)
<generator object <genexpr> at 0x109a0da50>
The more reason why the for loop and filter all need to be moved into a scope that stores idx; not just the filter.
On a different note, you can use itertools.islice instead of the inefficient logic you're using to print a slice of the generator expressions:
from itertools import islice
for skip_list in skip_lists:
for num in islice(skip_list, 10):
print("{}, ".format(num), end="")
print()

How to I write a recursive function for split even and odd indices of array?

This is question for my interview.
Write a recursive function that does the following:
Input: An array A of length N. N is an even number and N >= 2.
Output: A reordered array B. The first half of B contains A’s elements with even indices. The second half of B contains A’s elements with odd indices. Convention: the first index of an array is 0 (and thus it is an even number).
Input 1: [4, 8, 12, 16]
For this array, the indices and the values are as follows:
Index: 0, 1, 2, 3
Value: 4, 8, 12, 16
Thus, the output is as follows:
Expected output 1: [4, 12, 8, 16]
ADDITIONAL TEST CASE
Input 2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Expected output 2: [1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
TASK
Write a recursive function in a programming language of your choice (as if you are writing real code to be used on a production server) for the above problem
In addition to the main function, you are free to write helper functions (if needed)
The code should have as few lines as possible (but it should still be clear and readable)
Note: Your recursive function must show the 'spirit' of a recursive function (not just the recursive form of a for loop)
Here is my code:
def slove(array, deep=0):
'''para:
array: list input.
return: list.
!!!Do not set value for deep!!!'''
if len(array) > 2:
if deep > 0:
for i in xrange(0, len(array), 2):
array[i], array[i + 1] = array[i + 1], array[i]
left = array[0]
right = array[-1]
array = array[1:-1]
array = slove(array, deep + 1)
array.insert(0, left)
array.append(right)
return array
else:
array[0], array[-1] = array[-1], array[0]
return array
if __name__ == '__main__':
array = map(int, raw_input('Enter array with sep is space key: ').split(' '))
# array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print slove(array)
He said that it is wrong because I use loop in program. He is correct? So how to solve it?
Why not just use slicing?
lst = [11,12,13,14,15,16]
lst[0::2] + lst[1::2]
Returns:
[11, 13, 15, 12, 14, 16]
This pseudocode function might help:
Let A[n] and B[n] be the 2 arrays where n is the size.
Then we will call the following method rearrange(0,0):
rearrange(int i, int j) {
b[j] = a[i];
b[j+n/2] = a[i+1];
if (j < n/2-1)
rearrange(i+2,j+1);
}
In this method, i jumps 2 times each therefore the odd items get stored in the first half of the output array. For the second half, j+n/2 saves the even items.
This is one (awkward) way to do it:
def even_odd_split(seq):
"""
>>> even_odd_split([4, 8, 12, 16])
[4, 12, 8, 16]
>>> even_odd_split([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[1, 3, 5, 7, 9, 2, 4, 6, 8, 10]
"""
assert(len(seq) % 2 == 0)
assert(len(seq) > 1)
def _split(seq):
if len(seq) == 0: return [], []
a, b = _split(seq[2:])
return [seq[0]] + a, [seq[1]] + b
a, b = _split(seq)
return a + b
if __name__ == '__main__':
import doctest
doctest.testmod()
I would solve it like this:
def f(l):
if len(l) == 1:
# only one element left
return l
if len(l) % 2 == 0:
# length is even
return l[:1] + f(l[1:])
else:
# length is odd
return f(l[1:]) + l[:1]
Every invocation of the function removes one element from the list and either puts it at the beginning or at the end of the resulting list.
It does not produce the given “expected” outputs, because the elements of the list appear in another order than they appear in the input list, but it matches the specification… and also, I think it’s pretty simple.

Python: How to countdown a number, and append that countdown to a list

Here's my attempt at creating a countdown in which all the numbers get appended to a list.
timeleft = 3
num1 = 24 - timeleft
mylist = []
def countdown():
while num1 != 0:
num1 -= 1
mylist.append(num1)
countdown()
This is a small section of a schedule making app I'm making.
Instead of using global variables, I'd write a countdown function which accepts a start parameter and returns a list like this:
def countdown(start):
return list(range(start,0,-1))
Demo:
timeleft = 3
num1 = 24 - timeleft
cd = countdown(num1)
print(cd) # [21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
If you want to count to zero use range(start,-1,-1).
def countdown(time_left):
return [x for x in range(24 - time_left, -1, -1)]
Test:
>>> countdown(20)
[4, 3, 2, 1, 0]
>>> countdown(15)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>>
In Python 2, just return the call to range, which returns a list:
def countdown2(x, y=0):
return range(x, y-1, -1)
In Python 3, need to materialize range in a list:
def countdown2(x, y=0):
return list(range(x, y-1, -1))
To actually append to a list:
def countdown(x, y=0):
'''countdown from x to y, return list'''
l = []
for i in range(x, y-1, -1): # Python 2, use xrange
l.append(i)
return l
But a direct list would be standard approach here, not a list comprehension.

Equivalent of Haskell scanl in python

I would like to know if there is a built in function in python for the equivalent Haskell scanl, as reduce is the equivalent of foldl.
Something that does this:
Prelude> scanl (+) 0 [1 ..10]
[0,1,3,6,10,15,21,28,36,45,55]
The question is not about how to implement it, I already have 2 implementations, shown below (however, if you have a more elegant one please feel free to show it here).
First implementation:
# Inefficient, uses reduce multiple times
def scanl(f, base, l):
ls = [l[0:i] for i in range(1, len(l) + 1)]
return [base] + [reduce(f, x, base) for x in ls]
print scanl(operator.add, 0, range(1, 11))
Gives:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Second implementation:
# Efficient, using an accumulator
def scanl2(f, base, l):
res = [base]
acc = base
for x in l:
acc = f(acc, x)
res += [acc]
return res
print scanl2(operator.add, 0, range(1, 11))
Gives:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Thank you :)
You can use this, if its more elegant:
def scanl(f, base, l):
for x in l:
base = f(base, x)
yield base
Use it like:
import operator
list(scanl(operator.add, 0, range(1,11)))
Python 3.x has itertools.accumulate(iterable, func= operator.add). It is implemented as below. The implementation might give you ideas:
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
total = next(it)
yield total
for element in it:
total = func(total, element)
yield total
Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), which gives the possibility to name the result of an expression, we can use a list comprehension to replicate a scan left operation:
acc = 0
scanned = [acc := acc + x for x in [1, 2, 3, 4, 5]]
# scanned = [1, 3, 6, 10, 15]
Or in a generic way, given a list, a reducing function and an initialized accumulator:
items = [1, 2, 3, 4, 5]
f = lambda acc, x: acc + x
accumulator = 0
we can scan items from the left and reduce them with f:
scanned = [accumulator := f(accumulator, x) for x in items]
# scanned = [1, 3, 6, 10, 15]
I had a similar need. This version uses the python list comprehension
def scanl(data):
'''
returns list of successive reduced values from the list (see haskell foldl)
'''
return [0] + [sum(data[:(k+1)]) for (k,v) in enumerate(data)]
>>> scanl(range(1,11))
gives:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
As usual, the Python ecosystem is also overflowing with solutions:
Toolz has an accumulate capable of taking a user-supplied function as an argument. I tested it with lambda expressions.
https://github.com/pytoolz/toolz/blob/master/toolz/itertoolz.py
https://pypi.python.org/pypi/toolz
as does more_itertools
http://more-itertools.readthedocs.io/en/stable/api.html
I did not test the version from more-itertools, but it also can take a user-supplied function.

Categories