I'm not sure what I'm doing wrong with my code here in getting a recursive pascal's triangle to work in python. Any help is kindly appreciated :)
n = 5
def printPascal(n):
Pascal_List = []
if n == 0:
Pascal_List.append([1])
return Pascal_List
if n == 1:
Pascal_List.append([1])
Pascal_List.append([1,1])
return Pascal_List
else:
new_row = [1]
final_r = printPascal(n - 1)
last_row = final_r[-1]
for k in range(1, last_row[-1]):
new_row.append(final_r[k] + final_r[k - 1])
new_row += last_row
final_r.append(new_row)
return final_r
print(printPascal(n))
You've made a few confusions in the loop that builds a new line. range(1, last_row[-1]) doesn't really make sense; you want to iterate over the indices of the last row, ie range(len(last_row)). You've also mixed up final_r and last_row on the next line.
Here is a corrected version of your code :
n = 5
def printPascal(n):
Pascal_List = []
if n == 0:
Pascal_List.append([1])
return Pascal_List
if n == 1:
Pascal_List.append([1])
Pascal_List.append([1,1])
return Pascal_List
else:
new_row = [1]
final_r = printPascal(n - 1)
last_row = final_r[-1]
for k in range(len(last_row)-1):
new_row.append(last_row[k] + last_row[k + 1])
new_row.append(1)
final_r.append(new_row)
return final_r
print(printPascal(n))
There is a better method to do this using the general formula for Pascal's triangle (n choose k), but I will not go into that.
Looking at your code, I'm guessing you are trying to add the previous two numbers from the previous row to get the next number.
Change replace with this in your else condition:
#It should be length instead.
for k in range(1, len(last_row)):
new_row.append(last_row[k] + last_row[k - 1])
#You need to add the 1 at the end
new_row.append(1)
#zale already explained the problem with your for loop, no need to repeat that. However, note that you can make your code a good deal simpler:
no need for the special treatment of the n == 1 case
you can make the second part much simpler by padding the last line with zeros
Try this:
def printPascal(n):
if n == 0:
return [[1]]
else:
final_r = printPascal(n - 1)
last = [0] + final_r[-1] + [0] # note: this does not modify final_r
new_row = [last[k] + last[k - 1] for k in range(1, len(last))]
return final_r + [new_row]
Related
download the int input to array until is not smaller than previous one
except first, I'm trying this way.
So this would look like this:
4, 1, 2, 1 and now break
I have no clue what to do, I've tryed many ways like double for loop but no one of them work
def make_list(size: int):
return [int(input("enter element of the array:\n")) for _ in range(0, size)]
if __name__ == '__main__':
size = 5
so not sure if I understood the question (not very good at english), but I tried a little something that seems to give the output you wanted. Not very clean at the moment, so might update later.
def make_list(size: int):
if(size > 0):
tab = []
firstNb = get_input()
tab.append(firstNb)
if(size > 1):
lastNb = get_input()
tab.append(lastNb)
for _ in range(0, size - 1):
nb = get_input()
tab.append(nb)
if(nb < lastNb):
return tab
lastNb = nb
return tab
else:
return []
def get_input():
return int(input("enter element of the array:\n"))
if __name__ == '__main__':
size = 5
result = make_list(size)
print(result)
I solved that, maybe not in pretty way ( somethign does not work with list comprehension)
def create_array(size: int) -> [int]:
x = [(int(input("enter element of the array:\n")))]
# return ["break" if x[i] < x[i - 1] else int(input("enter element of the array:\n")) for i in range(0, size)] somethign wrong there
for i in range(0, size):
x.append(int(input("enter element of the array:\n")))
if x[i + 1 ] < x[i - 1]:
return x
return x
if __name__ == '__main__':
size = 5
print(create_array(size))
How can I get this to print all triplets that have a sum less than or equal to a target? Currently this returns triplets that are = to the target. I've tried to change and think but can't figure out
def triplets(nums):
# Sort array first
nums.sort()
output = []
# We use -2 because at this point the left and right pointers will be at same index
# For example [1,2,3,4,5] current index is 4 and left and right pointer will be at 5, so we know we cant have a triplet
# _ LR
for i in range(len(nums) - 2):
# check if current index and index -1 are same if same continue because we need distinct results
if i > 0 and nums[i] == nums[i - 1]:
continue
left = i + 1
right = len(nums) - 1
while left < right:
currentSum = nums[i] + nums[left] + nums[right]
if currentSum <= 8:
output.append([nums[i], nums[left], nums[right]])
# below checks again to make sure index isnt same with adjacent index
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
# In this case we have to change both pointers since we found a solution
left += 1
right -= 1
elif currentSum > 8:
left += 1
else:
right -= 1
return output
So for example input array is [1,2,3,4,5] we will get the result (1,2,3),(1,2,4),(1,2,5),(1,3,4) Because these have a sum of less than or equal to target of 8.
The main barrier to small changes to your code to solve the new problem is that your original goal of outputting all distinct triplets with sum == target can be solved in O(n^2) time using two loops, as in your algorithm. The size of the output can be of size proportional to n^2, so this is optimal in a certain sense.
The problem of outputting all distinct triplets with sum <= target, cannot always be solved in O(n^2) time, since the output can have size proportional to n^3; for example, with an array nums = [1,2,...,n], target = n^2 + 1, the answer is all possible triples of elements. So your algorithm has to change in a way equivalent to adding a third loop.
One O(n^3) solution is shown below. Being a bit more clever about filtering duplicate elements (like using a hashmap and working with frequencies), this should be improvable to O(max(n^2, H)) where H is the size of your output.
def triplets(nums, target=8):
nums.sort()
output = set()
for i, first in enumerate(nums[:-2]):
if first * 3 > target:
break
# Filter some distinct results
if i + 3 < len(nums) and first == nums[i + 3]:
continue
for j, second in enumerate(nums[i + 1:], i + 1):
if first + 2 * second > target:
break
if j + 2 < len(nums) and second == nums[j + 2]:
continue
for k, third in enumerate(nums[j + 1:], j + 1):
if first + second + third > target:
break
if k + 1 < len(nums) and third == nums[k + 1]:
continue
output.add((first, second, third))
return list(map(list, output))
I am trying to implement ZigZag from LeetCode. Somehow during the second recursive call my second for loop within "addElements" retains the value from the last call. Why does this happen?
I have shared the output below - my question is in regards to how beg and end stay the same value until 3, then beg moves to 6 as expected but end remains at 3.
https://leetcode.com/problems/zigzag-conversion/
class Solution:
def convert(self, s: str, numRows: int) -> str:
row = [''] * len(s)
self.s = s
self.numRows = numRows
self.final_grid = []
for i in range(numRows):
self.final_grid.append(list(row))
self.addElements(0, 0)
final_arr = []
for i in self.final_grid:
final_arr += i
final_word = ''
for i in final_arr:
if i != "":
final_word += i
return (final_word)
def addElements(self, count, column):
print(column, "beg")
for i in range(self.numRows):
if count > len(self.s) - 1:
break
self.final_grid[i][column] = self.s[count]
count += 1
for i in range(1, self.numRows - 1):
if count > len(self.s) - 1:
break
self.final_grid[self.numRows - i - 1][column + i] = self.s[count]
count += 1
print(column, "end")
self.addElements(count, column + self.numRows - 1)
INPUT: "PAYPALISHIRING" 4
STDOUT:
0 beg
0 end
3 beg
3 end
6 beg
3 end **why does this stay at 3?
6 beg
0 end
3 beg
3 end
6 beg
3 end
6 beg
Output: "PINALSIGYAHRGPIG"
Expected: "PINALSIGYAHRPI"
The problem appears to be this block:
for i in range(1, self.numRows - 1):
if count > len(self.s) - 1:
break
self.final_grid[self.numRows - i - 1][column + i] = self.s[count]
count += 1
print(column, "end")
self.addElements(count, column + self.numRows - 1)
Here, you are recursing for every element in the loop. You probably meant:
def addElements(self, count, column):
for i in range(self.numRows):
if count >= len(self.s):
return # <-- return instead of break
self.final_grid[i][column] = self.s[count]
count += 1
for i in range(1, self.numRows - 1):
if count >= len(self.s):
return # <-- return instead of break
self.final_grid[self.numRows-i-1][column+i] = self.s[count]
count += 1
self.addElements(count, column + self.numRows - 1)
#^^^ move this outside of the loop
With these changes, the output matches expected: "PINALSIGYAHRPI". The code is still a bit awkward and the various conditionals are strangely placed, doing double duty as pre/post conditions, so I'd consider a re-write.
Caveat: I've only taken a look at this problem and I'm not vouching that this code will work on the remainder of the tests. For one, it uses a huge amount of memory, so there is likely a way to build the result without creating a giant n x m array. There are other minor inefficiencies, like building the result array character by character, then building the result string from the array (runs in quadratic time because strings are immutable).
Instead of:
final_arr = []
for i in self.final_grid:
final_arr += i
final_word = ''
for i in final_arr:
if i != "":
final_word += i
return (final_word)
use:
return "".join(map("".join, self.final_grid))
Instead of:
row = [''] * len(s)
consider:
row = [''] * ((len(s) // 2) + 1)
Because the last element of the for loop stores the last variable.
To make so that you don't have that variable type del variable if you try to use that variable without reassigning a new value, it will throw an error
In this function, I want to return a value when the if statement is executed.
Since Python always returns something, it returns None.
def Persistence(number, counter):
numArr = [int(i) for i in str(number)]
result = 1
data = None
for j in numArr:
result *= j
if len(str(number)) == 1:
data = str(f'Done. {counter} steps taken')
print(data)
# return data
else:
counter = counter + 1
Persistence(result, counter)
# return data
print(Persistence(333,0))
Maybe I put the return keyword in the wrong place (I checked by putting it in two different places, marked as a comment) or something else, but I couldn't figure it out.
Please help me out. Also, if there is another way to count the recursion steps besides my technique, please let me know.
Maybe try this :
def Persistence(number, counter):
numArr = [int(i) for i in str(number)]
result = 1
for j in numArr:
result *= j
if len(str(number)) == 1:
return str(f'Done. {counter} steps taken')
counter = counter + 1
return Persistence(result, counter)
print(Persistence(333,0))
Hope it helps
The issue is that you're not setting the value from the else call to persistence to anything. The following code return the data value for me:
def Persistence(number, counter):
numArr = [int(i) for i in str(number)]
result = 1
data = None
for j in numArr:
result *= j
if len(str(number)) == 1:
data = str(f'Done. {counter} steps taken')
print(data)
return data
else:
counter = counter + 1
data = Persistence(result, counter)
return data
x = Persistence(333, 0)
Then if we print x:
print(x)
# Done. 3 steps taken
Your logic to count the recursion steps is basically correct, you just need to place the return statements for both the:
1)Base case
2)The recursive call itself
The following modification to your code will do the trick of what you are asking:
def Persistence(number, counter):
numArr = [int(i) for i in str(number)]
result = 1
data = None
for j in numArr:
result *= j
if len(str(number)) == 1:
data = str(counter)
return data
else:
counter = counter + 1
return Persistence(result, counter)
print(Persistence(333,0))
The above code will return the output of:
3
Please note that the reason you were getting "None" as the output in your original code is because you were not making a return at the actual recursive call itself: **return** Persistence(result, counter)
So when you ran print(Persistence(333,0)) it was returning nothing resulting in the None.
This question is better to learn about recursion than you may think. But we won't muddy the waters by mixing recursion (functional style) with statements and side effects (imperative style).
It looks like you're trying to calculate multiplicative root and persistence. Instead of putting all concerns of the computation into a single function, break it down into sensible parts -
def digits (n = 0):
if n < 10:
return [ n ]
else:
return digits (n // 10) + [ n % 10 ]
def product (n = 0, *more):
if not more:
return n
else:
return n * product (*more)
def mult_root (n = 0):
if n < 10:
return [ n ]
else:
return [ n ] + mult_root (product (*digits (n)))
def mult_persistence (n = 0):
return len (mult_root (n)) - 1
print (mult_persistence (333))
# 3
print (mult_root (333))
# [ 333, 27, 14, 4 ]
So I have the code
def formula(n):
while(n < 11):
answera = 15/(-4)** n
print(answera)
n = n + 1
formula(1)
How can I add the outputs in condescending order?
For example,
first_output = (the output of n = 1)
second_output = (the output of n = 1) + (the output of n = 2)
third_output = (the output of n = 1) + (the output of n = 2) + (the output of n = 3)
and so on..
you need to define the variable answera outside the while loop, so that its shope should exists outside the loop , so that when you return the value the fully updated value can be returned. Something like this.
def formula(n):
answera = 0
while(n < 11):
answera += 15/(-4)** n
print(answera)
n = n + 1
print(answera)
formula(1)
Now it should give you the right result.
def formula(n):
while(n < 11):
answera += 15/(-4)** n
print(answera)
n = n + 1
The idea is that you will need to accumlate the value of 15/(-4)**n in one of the variables.. (here the answera) and keep printing it out.
I hope this answers your question.
There's some ambiguity in your question; do you want the sum of 'answera', or the sum of 'formula'?
If 'answera', then you can just replace "print" with "yield" and call "sum":
def formula(n):
while(n < 11):
answera += 15/(-4)** n
yield answera
n = n + 1
sum(formula(2))
This makes 'formula' a generator, and "sum" will iterate that generator until it's exhausted.
If you want the sum of multiple 'formula' calls, then follow the KISS principle, and wrap your function with another function:
# assuming that 'formula' is a generator like above
def mega_formula(iterations):
total = []
for i in range(1, iterations + 1): # b/c range indexs from zero
total.append(sum(formula(i))
return sum(total)