List append in recursion - python

I am unable to make a pascal triangle. I need to append to list elements in recursion, but the result of my work is list appending in list. Can u help me to do it?
My testing code is:
def list(row):
if(row is 0):
return 0
return [row, list(row-1)]
If I use it, I will return list in list. I need elements in list
print(list(10))
Output:
[10, [9, [8, [7, [6, [5, [4, [3, [2, [1, 0]]]]]]]]]]
Expected output:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Regarding your specific function, here's one way you could write it
def foo (row):
if row == 0:
return [0]
else:
return [row] + foo (row - 1)
print(foo(10))
# [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Perhaps a more "pythonic" way of writing that would be
print([10 - x for x in range (0, 11)])
# [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Regarding pascal's triangle, here's one way you can write the program using an auxiliary helper and continuation passing style – for those wondering, this choice was made so that the result could be assembled in a straightforward manner and the recursive call is in tail position, meaning this function could easily be put on a trampoline to be made stack-safe if necessary
def sliding (n,xs):
if n > len(xs):
return []
else:
return [xs[0:n]] + sliding(n, xs[1:])
def pascal (n):
def aux (m, prev, k):
if n == m:
return k([prev])
else:
return aux(m + 1, [1] + [x + y for (x,y) in sliding(2, prev)] + [1], lambda rest: k([prev] + rest))
return aux(1, [1], lambda x: x)
for line in pascal(5):
print(line)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]

What you want is probably this:
return [row] + list(row-1)
This creates a list with one element row and adds the other list on top of it.

It sounds like you want to concatenate the list [x] with the list returned as a result of calling list(x-1). The nice thing about lists in python is that the + operator does exactly this. If we change the final return statement to return [x] + list(x-1) we're headed in the right direction. You'll then notice that you run into trouble when x is 0 becuase you cant add a list to an integer, so you'll want to change your base case to return [0]. Finally, as mentioned, it's best to avoid declaring names that overwrite python built in functions (list is one), so let's rename your function to my_list:
def my_list(row):
if row == 0:
return [0]
return [row] + my_list(row-1)
This doesn't quite get you to pascal's triangle, but hopefully you're off on the right course.

You can create a recursive range function that outputs your expected results:
def rec_range(n):
return [n] + rec_range(n-1) if n else [0]
>>> rec_range(10)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Hope it helps.
Or just use range (xrange in python2.x):
>>> list(range(10+1))[::-1] # reverse the list
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

You can create a Pascal's triangle using the given way
def pascal(rows):
for i in range (rows):
value=1
List = [value]
for j in range (i):
value = value * ( i-j ) * 1 / ( j + 1 )
List.append(int(value))
print(List)
pascal(5)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]

Related

How to create an output list which is the sum of alternating elements from an input number_list

I'm trying to sum the even and odd-indexed elements of a list together without the use of the sum() method, but something is going wrong. I'm new to Python so help would be appreciated.
An example would be input number_list as [1, 2, 3, 4] then the output list will be [4, 6], which is from the sum of the even-numbered elements 1 and 3, and the odd-numbered elements 2 and 4 from the list number_list. Similarly, [5, 8, 3, 2, 6, 7, 1] would have an output list of [8, 10, 9, 9, 5].
This is my code:
number_list = [2, 6, 3, 5, 9, 1, 7]
res=[0, 0, 0, 0, 0, 0]
for i in range(0, len(number_list)):
if(i % 2):
res[1] += number_list[i]
else :
res[0] += number_list[i]
print("Input List: {0}\n".format(number_list))
print("Output List: {0}\n".format(res))
I think the following is what you were going for; your first attempt was definitely on target:
!/usr/bin/env python3
number_list = [2, 6, 3, 5, 9, 1, 7]
i = 0
r = [0,0]
for n in number_list:
if (i % 2) == 0:
# Even
r[0] += n
else :
# Odd
r[1] += n
i += 1
print(" Input List: {0}". format(number_list))
print("Output List: {0}". format(r))
The result is:
Input List: [2, 6, 3, 5, 9, 1, 7]
Output List: [21, 12]
There are some simplifications here, namely throwing out Python nuances and just looking at iterating over a list of numbers, determining whether they are in the even or odd position (the i index), and adding (summing) them to the base r array. Is this the most compact and optimized Python code you will encounter? No. But is it clear as to what you're trying to do - I think so.
Joe's answer is absolutely correct. However more compact answer would be..
r = [0,0]
for n, val in enumerate(number_list):
j = n % 2
r[j] += val
print(" Input List: {0}". format(number_list))
print("Output List: {0}". format(r))

Slice list in python

I need to slice a list using python 3.7, and slice should contains two elements, if at the end we got one elements (like below), that's last element should go to previous part.
def solution(A):
l = len(A)
size = 2
for i in range(1, len(A), size):
print(A[i:i+2])
solution([4,2,2,5,1,5,8,9])
Output:
[2, 2]
[5, 1]
[5, 8]
[9]
Desire output:
[2, 2]
[5, 1]
[5, 8, 9]
Thanks for your help
def solution(A):
l = len(A)
size = 2
groups = [ A[i:i+size] for i in range(1, len(A), size) ]
if len(groups[-1]) < size:
groups[-2].extend(groups.pop())
for x in groups:
print(x)
Works for every value of size, not just 2.
You could just check if the next loop iteration will go too far, and if so print the entire list and stop.
Like so
def solution(A):
l = len(A)
size = 2
for i in range(1, len(A), size):
print(i)
if i+2*size > len(A):
print(A[i:])
break
else:
print(A[i:i+2])
def solution(A):
l = len(A)
size = 2
for i in range(0, len(A), size):
if l%2!=1 and i==l-3: #if the length is odd and i is the third last
print(A[i:i+3])
break
else:
print(A[i:i+2])
solution([4,2,2,5,1,5,8,9])
This function will do the trick (I'm not very happy with it, and I'm sure that there must be a better way out there, but it will do for now).
def listSlicing(raw_list, slice_length):
# Get the number of elements that will be left out when the list is sliced
extra_elements = len(raw_list)%slice_length
# Create a list of slices. Do not go to the last element
sliced_list = [raw_list[i:i+slice_length] for i in range(0, len(raw_list)-extra_elements, slice_length)]
# Access the last item of the sliced list and append the extra elements to it
if extra_elements == 0:
return sliced_list # No need to change the last value
else:
sliced_list[-1].extend(raw_list[-extra_elements:])
return sliced_list
l = [4,2,2,5,1,5,8,9,10]
listSlicing(l, 2)
# Will return [[4, 2], [2, 5], [1, 5], [8, 9, 10]]
In case there is only space for one slice (for example, assume a slice_length of 5 instead of 2), the function will return only a single list, as, after creating the first slice, the remaining 4 items (5, 8, 9, 10) will be appended to the first slice itself, effectively returning the same list again.
def func(a, size):
c=[]
if size==0 or size<0:
return []
if size>=len(a):
return a
c = [a[i:i+size] for i in range(0,(len(a)//size)*size,size) if i%size==0]
c[-1].extend(a[(len(a)//size)*size:])
return c
a = [4,2,2,5,1,5,8,9, 10]
print(func(a, 2))
print(func(a, 111))
print(func(a, 9))
print(func(a, 5))
output
[[4, 2], [2, 5], [1, 5], [8, 9, 10]]
[4, 2, 2, 5, 1, 5, 8, 9, 10]
[4, 2, 2, 5, 1, 5, 8, 9, 10]
[[4, 2, 2, 5, 1, 5, 8, 9, 10]]

How to merge k sorted arrays, solution didn't work allowing duplicates.!

Given k sorted arrays of size n each, merge them and print the sorted output.
The algorithm I followed is
iterate of over each array
pick the ith index in k arrays
insert() in minheap
delMin() and append result array.
from heapq import heappop, heappush
def merge_k_arrays(list_of_lists):
result = [] #len(list_of_lists[0])*len(list_of_lists)
minHeap= []
n, k=0,0
print(list_of_lists)
while n < len(list_of_lists[0]):
if n ==0:# initial k size heap ready
while k < len(list_of_lists):
element= list_of_lists[k][n]
heappush(minHeap ,element )
k+=1
result.append(heappop(minHeap))
else: # one at a time.
k =0
while k < len(list_of_lists):
element = list_of_lists[k][n]
heappush(minHeap , element)
result.append(heappop(minHeap))
k+=1
n += 1
# add the left overs in the heap
while minHeap:
result.append(heappop(minHeap))
return result
Input:
input = [ [1, 3, 5, 7],
[2, 4, 6, 8],
[0, 9, 10, 11],
]
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
input:
input = [ [1, 3, 5, 7],
[2, 4, 6, 8],
[3, 3, 3, 3],
[7, 7, 7,7]
]
output:
[0, 1, 2, 3, 3, 3, 4, 5, 6, 3, 7, 7, 7, 7, 3, 7, 8, 9, 10, 11]
Could anyone help me know what piece is missing from my algorithm in order to merge the duplicate arrays in the second input too?
from heapq import *
def mergeSort (arr):
n = len(arr)
minHeap = []
for i in range(n):
heappush(minHeap, (arr[i][0], i, arr[i]))
print(minHeap)
result = []
while len(minHeap) > 0:
num, ind, arr = heappop(minHeap)
result.append(num)
if len(arr) > ind + 1:
heappush(minHeap, (arr[ind+1], ind+1, arr))
return result
input = [ [1, 3, 5, 7],
[2, 4, 6, 8],
[0, 9, 10, 11],
[-100]
]
print(mergeSort(input))
To fix your code, move the result.append(heappop(minHeap)) in your second nested while loop to the outside of the nested while loop, like in your first nested while loop. This will make your code work.
else: # one at a time.
k =0
while k < len(list_of_lists):
element = list_of_lists[k][n]
heappush(minHeap , element)
k+=1
result.append(heappop(minHeap))
n += 1
If you have any space constraints, this is still problematic since you are adding nearly your entire input into the heap. If space is not an issue, there is a much cleaner way to write your solution:
def merge(A):
result = []
heap = [e for row in A for e in row]
heapify(heap)
for i in range(len(heap)):
result.append(heappop(heap))
return result
Otherwise, you will need to use a smarter solution that only allows the heap to have k elements in total, with one element from each list, and the new element you add each step should come from the origin list of the element that was just popped.

Skipping through one iteration of a loop

Say I had a list:
lis = [4, 8, 2, 4, 6]
And I want to go through each value in the list and double it but If I come across the number 2, after I double it I should skip the next number and only double the on after. For example, in the end my list should look like this.
lis = [8, 16, 4, 4, 12]
Can this be possible with a for loop?
The algorithm boils down what number you are using to double the items in the list (1 or 2). Here is my take on this problem:
lis = [4, 8, 2, 4, 6]
def double_with_my_condition(l, doubler=2):
for i in l:
yield i * doubler
if i == 2:
doubler = 1
continue
doubler = 2
new_lis = [*double_with_my_condition(lis)]
print(new_lis)
Outputs:
[8, 16, 4, 4, 12]
I wrote out a really simple solution that should be easy to understand since it appears you are a beginner
lis = [4, 8, 2, 4, 6]
new_lis = []
i = 0
while (i < len(lis)):
new_lis.append(lis[i] * 2)
if (lis[i] == 2):
if (i+1 < len(lis)):
new_lis.append(lis[i+1])
i = i+1
i = i+1
print(new_lis)
This creates a new list, loops through the old list, appends the doubled value to the new list, skips a number if the value at the index is 2.
This will work!
Method-1:
lis = [4, 8, 2, 4, 6]
for i in range(len(lis)-1, -1, -1):
if(lis[i-1] == 2):
continue
else:
lis[i] = lis[i]*2
lis
Method-2:
lis1 = [4, 8, 2, 4, 6]
indices = [i+1 for i, x in enumerate(lis1) if x == 2] #Storing indices of next to 2
lis2 = [i*2 for i in lis1]
for i in indices:
lis2[i] = lis1[i] # replacing the previous values
print(lis2)
You can also use list comprehensions
lis = [4, 8, 2, 4, 6]
print([lis[x] if lis[x - 1] == 2 else lis[x] * 2 for x in range(len(lis))])

Python - Remove between indexes of two values if it occurs twice in a list

Title is definitely confusing, so here's an example: Say I have a list of values [1,2,3,2,1,4,5,6,7,8]. I want to remove between the two 1s in the list, and by pythonic ways it will also end up removing the first 1 and output [1,4,5,6,7,8]. Unfortunately, due to my lack of pythonic ability, I have only been able to produce something that removes the first set:
a = [1,2,3,2,1,4,5,6,7]
uniques = []
junks = []
for value in a:
junks.append(value)
if value not in uniques:
uniques.append(value)
for value in uniques:
junks.remove(value)
for value in junks:
a.remove(value)
a.remove(value)
a[0] = 1
print(a)
[1,4,5,6,7]
Works with the first double occurrence and will not work with the next occurrence in a larger list. I have an idea which is to remove between the index of the first occurrence and the second occurrence which will preserve the second and not have me do some dumb thing like a[0] = 1 but I'm really not sure how to implement it.
Would this do what you asked:
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8]
def f(l):
x = l.copy()
for i in l:
if x.count(i) > 1:
first_index = x.index(i)
second_index = x.index(i, first_index + 1)
x = x[:first_index] + x[second_index:]
return x
So the output of f(a) would be [1, 4, 5, 6, 7, 8] and the output of f([1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]) would be [1, 4, 5, 15, 16].
if you want to find unique elements you can use set and list
mylist = list(set(mylist))
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
dup = [x for x in a if a.count(x) > 1] # list of duplicates
while dup:
pos1 = a.index(dup[0])
pos2 = a.index(dup[0], pos1+1)
a = a[:pos1]+a[pos2:]
dup = [x for x in a if a.count(x) > 1]
print a #[1, 4, 5, 15, 16]
A more efficient solution would be
a = [1, 2, 3, 2, 1, 4, 5, 6, 7, 8, 7, 6, 5, 15, 16]
pos1 = 0
while pos1 < len(a):
if a[pos1] in a[pos1+1:]:
pos2 = a.index(a[pos1], pos1+1)
a = a[:pos1]+a[pos2:]
pos1 += 1
print a #[1, 4, 5, 15, 16]
(This probably isn't the most efficient way, but hopefully it helps)
Couldn't you just check if something appears twice, if it does you have firstIndex, secondIndex, then:
a=[1,2,3,4,5,1,7,8,9]
b=[]
#do a method to get the first and second index of the repeated number then
for index in range(0, len(a)):
print index
if index>firstIndex and index<secondIndex:
print "We removed: "+ str(a[index])
else:
b.append(a[index])
print b
The output is [1,1,7,8,9] which seems to be what you want.
To do the job you need:
the first and the last position of duplicated values
all indexes between, to remove them
Funny thing is, you can simply tell python to do this:
# we can use a 'smart' dictionary, that can construct default value:
from collections import defaultdict
# and 'chain' to flatten lists (ranges)
from itertools import chain
a = [1, 2, 3, 2, 1, 4, 5, 6, 7]
# build dictionary where each number is key, and value is list of positions:
index = defaultdict(list)
for i, item in enumerate(a):
index[item].append(i)
# let's take first only and last index for non-single values
edges = ((pos[0], pos[-1]) for pos in index.values() if len(pos) > 1)
# we can use range() to get us all index positions in-between
# ...use chain.from_iterable to flatten our list
# ...and make set of it for faster lookup:
to_remove = set(chain.from_iterable(range(start, end)
for start, end in edges))
result = [item for i, item in enumerate(a) if i not in to_remove]
# expected: [1, 4, 5, 6, 7]
print result
Of course you can make it shorter:
index = defaultdict(list)
for i, item in enumerate([1, 2, 3, 2, 1, 4, 5, 6, 7]):
index[item].append(i)
to_remove = set(chain.from_iterable(range(pos[0], pos[-1])
for pos in index.values() if len(pos) > 1))
print [item for i, item in enumerate(a) if i not in to_remove]
This solution has linear complexity and should be pretty fast. The cost is
additional memory for dictionary and set, so you should be careful for huge data sets. But if you have a lot of data, other solutions that use lst.index will choke anyway, because they are O(n^2) with a lot of dereferencing and function calls.

Categories

Resources