Stuck on a problem where I am supposed to decrease the value of n by a value of k using Python Recursion.
If n = 10 and k = 2, my output should be:
10,8,6,4,2,0,2,4,6,8,10
n should decrease by k and then increase by k again.
I wrote the below code:
def pattern(n):
k = 2
if n <=0:
print(n, end= ",")
#pattern(n+k)
else:
print(n, end = ",")
pattern(n-k)
pattern(5)
but my output is:
5, 3, 1,-1
My answer should be:
5,3,1,-1,1,3,5
Here I've corrected your code:
def pattern(n, k, outer=True):
print(n, end=",")
if n > 0:
pattern(n - k, k, False)
if outer:
print(n)
else:
print(n, end=",")
pattern(10, 2)
pattern(5, 3)
I've made k an argument to pattern.
I've also fixed the recursive algorithm. I think the most crucial part is that
you need to print the number again after the recursive step.
There is also some logic to make sure no comma is printed at the end. This is a
little convoluted, and if you're willing to use generators there's a much nicer
way (that also removes the side-effects of the function, which is a plus):
def gen_pattern(n, k):
yield n
if n > 0:
yield from gen_pattern(n - k, k)
yield n
def fmt_gen_pattern(n, k):
return ",".join(map(str, gen_pattern(n, k)))
print(fmt_gen_pattern(10, 2))
print(fmt_gen_pattern(5, 3))
Here is the output generated by either of these:
10,8,6,4,2,0,2,4,6,8,10
5,2,-1,2,5
This is not the same output as you spelled out, but I'm pretty sure this is what
you meant.
Your method of recursion lacks the base case that will stop the recursion. Hence, it'll recurse infinitely and abort eventually.
Here are two correct approaches to do it.
def method1(current,direction,n,k):
if current<=0:
direction = 'Up'
if direction=='Up' and current>=n:
print(current,end=' ')
return
if direction=='Down':
print(current,end=' ')
method1(current-k,direction,n,k)
else:
print(current,end=' ')
method1(current+k,direction,n,k)
def method2(n,k):
if n<=0:
print(n,end=' ')
return
print(n,end=' ') # This print shows decreasing n
method2(n-k,k) # Recurse
print(n,end=' ') # This print shows increasing n
n = 5
k = 2
# assert k<=n, "k cannot be greater than n" # Optional check
print('Method 1')
method1(n,'Down',n,k)
print('\nMethod 2')
method2(n,k)
Output
Method 1
5 3 1 -1 1 3 5
Method 2
5 3 1 -1 1 3 5
Related
I have a solution to a problem that uses dynamic programming. I need help turning this from a recursive solution into an iterative one.
The function takes in a number and follows the three rules:
it may divide the number in half
it may subtract one
it may add one
until the number is 1. My goal is to find the minimum number of steps it takes to do this.
Here is my solution:
def solution(n):
n = int(n)
memo = {}
return memoized_fuel_injection_perfection(n, memo)
def memoized_fuel_injection_perfection(n, memo):
if n == 1:
return 0
if n == 2:
return 1
if n in memo:
return memo[n]
if n % 2 == 0:
if n not in memo:
memo[n] = memoized_fuel_injection_perfection(n//2, memo) + 1
return memo[n]
return min(memoized_fuel_injection_perfection(n-1, memo), memoized_fuel_injection_perfection(n+1, memo)) + 1
But when I input numbers larger than 300 digits long, I am getting a recursive error. How can I turn this into an iterative solution? Any help or guidance is appreciated.
Here is an iterative solution I created, but I am getting MemoryError with very large inputs. Is there some way I can optimize storing the variables so I don't have to compute them for every number?
def solution(n):
memo = {}
memo[0] = 0
memo[1] = 0
memo[2] = 1
n = int(n)
for i in range(3, n+1):
if i % 2 == 0:
memo[i] = memo[i//2] + 1
else:
memo[i] = min(memo[i//2], memo[i//2 + 1]) + 2
return memo[n]
The problem you said you're having with writing an iterative solution is the use of memoized_fuel_injection_perfection(n+1, memo), which makes it tricky to determine what order to compute results in. The key is that you cannot repeatedly go down this code path indefinitely. If you could, even your recursive solution would be invalid.
Immediately after a +1 or -1 operation, you always perform a divide-by-2. We can fuse the +1 or -1 with the divide-by-2, producing an operation that cannot increase the number. The core of an iterative solution would then look like this:
if n % 2 == 0:
table[n] = table[n//2] + 1
else:
table[n] = min(table[n//2], table[n//2+1]) + 2
Can you complete things from there? (You'll need a way to avoid computing results for every positive integer less than n.)
Here's my attempt:
def solution(n):
def is_even(n): # helper function
return n % 2 == 0
possible_nodes = {1} # 1 is the destination
consider = [n] # stack: numbers to be considered
while consider: # as long as non-empty
x = consider.pop() # now think about where can we move from x
if x in possible_nodes: # if it is already handled before
continue
if is_even(x): # if even, we just halve it
consider.append(x//2)
else: # otherwise, -1 or +1
consider += [x-1, x+1]
possible_nodes.add(x) # mark x as 'considered'
steps = {1: 0} # dict to store min steps
for x in filter(is_even, sorted(possible_nodes)): # odds calculated only when needed
if x//2 not in steps: # if x//2 was not computed, x//2 must be odd
steps[x//2] = min(steps[x//2 - 1], steps[x//2 + 1]) + 1
steps[x] = steps[x//2] + 1
return steps[n] if is_even(n) or n == 1 else min(steps[n-1], steps[n+1]) + 1
n = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003483983333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
print(solution(n)) # 2467
print(*(solution(i) for i in range(1, 21)))
# 0 1 2 2 3 3 4 3 4 4 5 4 5 5 5 4 5 5 6 5
The code basically consists of two steps. In the first step, it enumerates all the possible steps from n, under the rule that for x,
if x is even, we only consider x//2 as the next step; this strategy is adopted also in your code;
if x is odd, we consider x-1 and x+1 as the next step.
I did this because calculating the minimum steps for all values up to n is wasteful. (Actually at first I tried to do so by initiating something like [None] * n, but it seems like python cannot handle such a long list. Even if it can, I guess that would be extremely slow.)
The next step is calculating the minimum steps, starting from the smallest number. I address the problem of accessingsteps[x+1] by "not calculating steps[x] for odd x eagerly." We only calculate steps[x] for even x eagerly, but lazily for odd x.
The rationale is the following; by the time odd x is needed, it must be the case that x is either k//2 - 1 or k//2 + 1 for some even k, which must be larger than x + 1. Since x + 1 is even, step[x+1] must have been already calculated, by the construction of the for loop.
I was writing the solution to this codewars problem however I've ran into a bit of an issue.
Problem statement:
Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit, e.g.:
persistence(39) # returns 3, because 39=27, 27=14, 1*4=4 and 4 has only one digit
def persistence(n, t=1, x=0):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
if len(str(t)) > 1:
x += 1
return(persistence(t,x))
else:
return(x)
else:
return 0
I can't quite figure out what the error is in this code. My hunch is that it's either a parameter error or the way the return() value is placed.
In essence, the code for distilling an integer to it's multiples is correct, so I just added an extra parameter to persistence; setting x = 0 and making it so that each time the if condition was fulfilled it would increment that exact x value. Once the number was distilled, simply output x. Yet it continues to simply output 0 as the final answer. What's the problem here?
Edit: Solution was in the comments, didn't realise how the parameters were passing. Correct version is:
return(persistence(t,1,x))
Also had to set x = 1 for the logic to work on codewars.
There are 2 flaws in Your code:
return(persistence(t,x))
should be
return(persistence(t,1,x))
otherwise the value of x will be assigned to t and x will be defaulted to 0.
Then you must increment x directly after the first test, otherwise You will miss one iteration.
Another way to calculate this is not to switch over to strings, but to do it numerically:
def persistence(n):
iterations = 0; # no iterations yet
while n > 9: # while n has more than 1 digit:
product = 1 # neutrum for result product
while n > 0: # while there a digit to process:
digit = n % 10 # retrieve the right most digit
product *= digit # do the multiplication
n = n // 10 # cut off the processed digit
iterations += 1 # increment iterations
n = product # let n be the newly calculated product
return iterations # return the result
I think you your function's parameters work not as you expect them to do.
When you call function persistence(t, x), the first argument n should become t, and second argument x, should become new x. But in your function, x becomes new t because of their position.
It is quite useful to have bunch of print statements to reveal the bug.
def persistence(n, x=1, t=1):
print('x:', x)
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
print('t:', t)
if len(str(t)) > 1:
x += 1
print('x has changed:', x)
return persistence(t, x)
else:
return x
else:
return 0
print(persistence(39))
print('---------------')
print(persistence(999))
print('---------------')
print(persistence(4))
Passes all test cases with two changes:
You were not updating your n with the new t everytime
Your x was being set to 0 every time. That should be set to 1 in the beginning (default value)
def persistence(n, t=1, x=1):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
if len(str(t)) > 1:
x += 1
return (persistence(n=t, x=x))
else:
return (x)
else:
return 0
Actually, you can write it without needing both parameters t and n. Just one n is fine as shown below:
def persistence(n, x=1):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
t = 1
for i in number:
t = t * i
if len(str(t)) > 1:
return x + (persistence(n=t, x=x))
else:
return (x)
else:
return 0
How can I write a recursive backtracking function count(N,S) in which it prints all N-digit numbers such that the sum of each 3 consecutive digits in the number is exactly equal to S where N will be less than or equal to 10, and is from 0 to 27.
Code:
def count(S):
n = int(S)
if n % 3 == 0:
print(int(n / 3 - 1),int(n / 3),int(n / 3 + 1))
else:
print(None)
S = 27
count(S)
Sample Output:
8 9 10
I'm quite confused on how can I write this recursively.
Your current function is not recursive. To make it recursive, you'd basically have to call count(n-1, s) somewhere within the execution of count(n, s). One way to do it would be like this:
if n > 1, get possible solutions for n-1 and append any digit that still satisfied the condition
if n == 0 just return "" (it's a bit easier if the function returns strings, not actual integers)
As a generator function, this could look somewhat like this. Of course, you can just as well collect the results in a list and return them, or just get the count of such numbers and return that.
def count(n, s):
if n > 0:
for x in count(n-1, s):
for d in range(10):
y = str(d) + x
if len(y) < 3 or sum(map(int, y[:3])) == s:
yield y
else:
yield ""
for x in count(5, 15):
print(x)
I am working on a python algorithm to find the most frequent element in the list.
def GetFrequency(a, element):
return sum([1 for x in a if x == element])
def GetMajorityElement(a):
n = len(a)
if n == 1:
return a[0]
k = n // 2
elemlsub = GetMajorityElement(a[:k])
elemrsub = GetMajorityElement(a[k:])
if elemlsub == elemrsub:
return elemlsub
lcount = GetFrequency(a, elemlsub)
rcount = GetFrequency(a, elemrsub)
if lcount > k:
return elemlsub
elif rcount > k:
return elemrsub
else:
return None
I tried some test cases. Some of them are passed, but some of them fails.
For example, [1,2,1,3,4] this should return 1, buit I get None.
The implementation follows the pseudocode here:
http://users.eecs.northwestern.edu/~dda902/336/hw4-sol.pdf
The pseudocode finds the majority item and needs to be at least half. I only want to find the majority item.
Can I get some help?
Thanks!
I wrote an iterative version instead of the recursive one you're using in case you wanted something similar.
def GetFrequency(array):
majority = int(len(array)/2)
result_dict = {}
while array:
array_item = array.pop()
if result_dict.get(array_item):
result_dict[array_item] += 1
else:
result_dict[array_item] = 1
if result_dict[array_item] > majority:
return array_item
return max(result_dict, key=result_dict.get)
This will iterate through the array and return the value as soon as one hits more than 50% of the total (being a majority). Otherwise it goes through the entire array and returns the value with the greatest frequency.
def majority_element(a):
return max([(a.count(elem), elem) for elem in set(a)])[1]
EDIT
If there is a tie, the biggest value is returned. E.g: a = [1,1,2,2] returns 2. Might not be what you want but that could be changed.
EDIT 2
The pseudocode you gave divided into arrays 1 to k included, k + 1 to n. Your code does 1 to k - 1, k to end, not sure if it changes much though ? If you want to respect the algorithm you gave, you should do:
elemlsub = GetMajorityElement(a[:k+1]) # this slice is indices 0 to k
elemrsub = GetMajorityElement(a[k+1:]) # this one is k + 1 to n.
Also still according to your provided pseudocode, lcount and rcount should be compared to k + 1, not k:
if lcount > k + 1:
return elemlsub
elif rcount > k + 1:
return elemrsub
else:
return None
EDIT 3
Some people in the comments highligted that provided pseudocode solves not for the most frequent, but for the item which is present more that 50% of occurences. So indeed your output for your example is correct. There is a good chance that your code already works as is.
EDIT 4
If you want to return None when there is a tie, I suggest this:
def majority_element(a):
n = len(a)
if n == 1:
return a[0]
if n == 0:
return None
sorted_counts = sorted([(a.count(elem), elem) for elem in set(a)], key=lambda x: x[0])
if len(sorted_counts) > 1 and sorted_counts[-1][0] == sorted_counts[-2][0]:
return None
return sorted_counts[-1][1]
I'm new to programming and I'm trying to write a program in Python that will find the sum of the even numbers of the numbers below 4,000,000 in the Fibonacci sequence. I'm not sure what I'm doing wrong but nothing will print. Thanks for any help.
def fib():
listx = []
for x in range(4000000):
if x == 0:
return 1
elif x == 1:
return 1
else:
listx.append(fib(x - 1) + fib(x - 2))
return listx
def evens(fib):
y = 0
for x in fib():
if x % 2 == 0:
y += x
else:
continue
print (y)
Here's an approach that uses a generator to keep memory usage to a minimum:
def fib_gen(up_to):
n, m = 0, 1
while n <= up_to:
yield n
n, m = m, n + m
total = 0
for f in fib_gen(4000000):
if f % 2 == 0:
total += f
Another option:
def fib_gen(up_to, filter):
n, m = 0, 1
while n <= up_to:
if filter(n):
yield n
n, m = m, n + m
sum(fib_gen(4000000, lambda f: f % 2 == 0)) # sum of evens
sum(fib_gen(4000000, lambda f: f % 2)) # sum of odds
First things first, there appears to be some contention between your requirements and the code you've delivered :-) The text of your question (presumably taken from an assignment, or Euler #2) requests the ...
sum of the even numbers of the numbers below 4,000,000 in the Fibonacci sequence.
Your code is summing the even numbers from the first four million Fibonacci numbers which is vastly different. The four millionth Fibonacci number has, according to Binet's formula, north of 800,000 digits in it (as opposed to the seven digits in the highest one below four million).
So, assuming the text to be more correct than the code, you don't actually need to construct a list and then evaluate every item in it, that's rather wasteful on memory.
The Fibonacci numbers can be generated on the fly and then simply accumulated if they're even. It's also far more useful to be able to use an arbitrary method to accumulate the numbers, something like the following:
def sumFibWithCond(limit, callback):
# Set up initial conditions.
grandparent, parent, child = 0, 0, 1
accum = 0
# Loop until number is at or beyond limit.
while child < limit:
# Add any suitable number to the accumulator.
accum = accum + callback(child)
# Set up next Fibonacci cycle.
grandparent, parent = parent, child
child = grandparent + child
# Return accumulator when done.
return accum
def accumulateEvens(num):
# Return even numbers as-is, zero for odd numbers.
if num % 2 == 0:
return num
return 0
sumEvensBelowFourMillion = sumFibWithCond(4000000, accumulateEvens)
Of special note is the initial conditions. The numbers are initialised to 0, 0, 1 since we want to ensure we check every Fibonacci number (in child) for the accumulating condition. This means the initial value of child should be one assuming, as per the question, that's the first number you want.
This doesn't make any difference in the current scenario since one is not even but, were you to change the accumulating condition to "odd numbers" (or any other condition that allowed for one), it would make a difference.
And, if you'd prefer to subscribe to the Fibonacci sequence starting with zero, the starting values should be 0, 1, 0 instead.
Maybe this will help you.
def sumOfEvenFibs():
# a,b,c in the Fibonacci sequence
a = 1
b = 1
result = 0
while b < 4000000:
if b % 2 == 0:
result += b
c = a + b
a = b
b = c
return result