How do I modify this Fibonacci Sequence Problem? - python

I am trying to figure out how I can modify the code below to help solve the question given. However, instead of only being able to take 1 or 2 steps at a time, I want to make it so I can also take 3 steps.
You have a ladder of N steps (rungs). You can go up the ladder by taking either 1 step or two steps at a time, in any combination. How many different routes are there (combinations of 1 steps or 2 steps) to make it up the ladder?
Here is some code that I'm trying to modify:
def countP(n):
if (n == 1 or n == 2):
return n
return countP(n-1) + countP(n-2)
I've already tried this so far and I am not getting the correct answer:
def countP(n):
if (n == 1 or n == 2 or n == 3):
return n
return countP(n-1) + countP(n-2) + countP(n-3)
Any help of guidance would be of great help! Thanks

Your base case in the recursion for n = 3 is wrong.
For n = 3, the correct answer should be 4, but you are returning 3.
I suggest you to simplify the base case by using the following observations:
Utmost base case is when n <= 1 i.e when we have only one stair or no stair, hence the only way to climb is taking a step of 1 unit or 0 unit. Hence, number of ways is countP(0) = 1 and countP(1) = 1.
What happens when n > 1 ? Well, we have three options to take for first step - we can take m units (1 unit, 2 units or 3 units step) as first step provided m <= n.
If we can take 1 unit step as first step, we can reduce the sub-problem from countP(n) to countP(n-1).
If we can take 2 units step as first step, we can reduce the sub-problem from countP(n) to countP(n-2).
If we can take 3 units step as first step, we can reduce the sub-problem from countP(n) to countP(n-3).
So, our final count will be : countP(n - m) for all m <= n
Code will be as follows:
def countP(n):
if (n == 0 or n == 1):
return 1
count = 0
for m in [1, 2, 3]:
if m <= n:
count += countP(n - m)
return count

The line return n is correct for the first problem but not the second. Keep in mind that the result is supposed to be the number of possible routes you can take.
If you can take either one or two steps at a time, then when you have one rung left, there is only one thing to do: take one step. If you have two rungs left, you have two options: either take two steps, or take one step (one rung), then another (the second rung). So, somewhat by coindicence, for this version of the problem the number of routes in the base case happens to equal the number of rungs left.
If you can take either one, two or three steps at a time, then the number of routes when you have three rungs remaining is not three; there are more than three options. You will have to count how many options there are, and return that in the case where n == 3.

Related

How do I count how many times I've divided in a recursion?

I'm currently taking a course in Computer Science, I got an assignment to use either Python or pseudocode to ask the user to enter a digit, then divide it by 2, and then count how many divisions it takes to reach 1 (and add 1 more as it reaches 1). I've never coded before but I came up with this; but it only returns a 1 no matter what I input.
def divTime (t):
if d <= 1:
return t + 1
else:
return t + 1, divTime(d / 2)
d = input("Enter a number:")
t = 0
print (divTime)(t)
You can add 1 to the recursive call with the input number floor-divided by 2, until the input number becomes 1, at which point return 1:
def divTime(d):
if d == 1:
return 1
return 1 + divTime(d // 2)
so that:
print(divTime(1))
print(divTime(3))
print(divTime(9))
outputs:
1
2
4
This works:
def div_time(d, t=0):
if d < 1:
return t
else:
return div_time(d/2, t+1)
d = input("Enter a number:")
print(f"t = {div_time(int(d))}")
It always returns 1 because you're always passing it 0.
It looks like you're "thinking in loops" – you don't need a separate counter variable.
How many times does it take to divide:
k smaller than 2? None.
k greater than or equal to 2? One more than it takes to divide k // 2.
That is,
def divTime(x):
if x < 2:
return 0
return 1 + divTime(x // 2)
or
def divTime(x):
return 0 if x < 2 else 1 + divTime(x //2)
Instead of providing a straight forward answer, I'll break the problem out into a few steps for students:
Ignore the input and edge cases for now, let's focus on writing a function that solves the problem at hand, then we may come back to providing an input to this function.
Problem statement confusion - You will often divide an odd number with a remainder, skipping the exact number 1 due to remainders. There is ambiguity with your problem from dealing with remainders - we will reword the problem statement:
Write a function that returns the number of times it takes to divide an input integer to become less than or equal to 1.
The next part is identifying the type of algorithm that can solve this type of problem. Since we want to run the function an unknown amount of times using the same function, this seems to be a perfect use case of recursion.
Say I provide 10 as an input. We then want to say 10/2=5 (count 1), 5/2=2.5 (count 2), 2.5/2=1.25 (count 3), 1.25/2=0.625 (count 4), return [4] counts.
Now we know we need a counter (x = x+1), recursion, and a return/print statement.
class solution:
''' this class will print the number of times it takes to divide an integer by 2 to become less than or equal to 1 '''
def __init__(self):
#this global counter will help us keep track of how many times we divide by two. we can use it in functions inside of this class.
self.counter=0
def counter_2(self, input_integer):
#if the input number is less than or equal to 1 (our goal), then we finish by printing the counter.
if input_integer<=1:
print(self.counter, input_integer)
#if the input is greater than 1, we need to keep dividing by 2.
else:
input_integer=input_integer/2
#we divided by two, so make our counter increase by +1.
self.counter=self.counter+1
#use recursion to call our function again, using our current inputer_integer that we just divided by 2 and reassigned the value.
self.counter_2(input_integer)
s=solution()
s.counter_2(10)

Project Euler #25 - Can the performance be improved further?

The 12th term, F12, is the first term to contain three digits.
What is the index of the first term in the Fibonacci sequence to contain 1000 digits?
a = 1
b = 1
i = 2
while(1):
c = a + b
i += 1
length = len(str(c))
if length == 1000:
print(i)
break
a = b
b = c
I got the answer(works fast enough). Just looking if there's a better way for this question
If you've answered the question, you'll find plenty of explanations on answers in the problem thread. The solution you posted is pretty much okay. You may get a slight speedup by simply checking that your c>=10^999 at every step instead of first converting it to a string.
The better method is to use the fact that when the Fibonacci numbers become large enough, the Fibonacci numbers converge to round(phi**n/(5**.5)) where phi=1.6180... is the golden ratio and round(x) rounds x to the nearest integer. Let's consider the general case of finding the first Fibonacci number with more than m digits. We are then looking for n such that round(phi**n/(5**.5)) >= 10**(m-1)
We can easily solve that by just taking the log of both sides and observe that
log(phi)*n - log(5)/2 >= m-1 and then solve for n.
If you're wondering "well how do I know that it has converged by the nth number?" Well, you can check for yourself, or you can look online.
Also, I think questions like these either belong on the Code Review SE or the Computer Science SE. Even Math Overflow might be a good place for Project Euler questions, since many are rooted in number theory.
Your solution is completely fine for #25 on project euler. However, if you really want to optimize for speed here you can try to calculate fibonacci using the identities I have written about in this blog post: https://sloperium.github.io/calculating-the-last-digits-of-large-fibonacci-numbers.html
from functools import lru_cache
#lru_cache(maxsize=None)
def fib4(n):
if n <= 1:
return n
if n % 2:
m = (n + 1) // 2
return fib4(m) ** 2 + fib4(m - 1) ** 2
else:
m = n // 2
return (2 * fib4(m - 1) + fib4(m)) * fib4(m)
def binarySearch( length):
first = 0
last = 10**5
found = False
while first <= last and not found:
midpoint = (first + last) // 2
length_string = len(str(fib4(midpoint)))
if length_string == length:
return midpoint -1
else:
if length < length_string:
last = midpoint - 1
else:
first = midpoint + 1
print(binarySearch(1000))
This code tests about 12 times faster than your solution. (it does require an initial guess about max size though)

Dynamic programming stack of plates [duplicate]

I've been given a little brainteaser to solve.
The task is to make a function with a single integer parameter. You have to figure out how many different combination of tower patterns you can make with that given amount of bricks (each proceeding tower must be less in height than one previous, kind of like). There must be 2 or more towers, one right next to the other.
For example, if you were given 3 blocks you can only produce 1 combination of towers, one with a height of 2 and its neighbor having a height of 1:
|
| |
2 1
Given 4 you can only still produce one combination since the next tower must be shorter than the previous:
|
|
| |
3 1
Given 5 you can produce 2 combinations:
|
|
|
| |
4 1
|
| |
| |
3 2
I have a function that can do all of this, however they give the example that 200 blocks should produce 487067745. Which my function simply does not do. I don't know what I am doing wrong. A push in the right direction would be very much appreciated. My function now looks like this:
def answer(num):
# divide the blocks so we have two towers, one with a height of n-1 and
# the other with a height of one
l1 = num-1
l2 = 1
combinations = 0
while True:
if l1 > l2:
# add 1 to the combinations along with how many combinations we
# can make using the blocks from tower two
combinations += 1 + answer(l2)
elif l1 == l2:
# see if we can make additional towers out of the rightmost tower
# and add that to the combinations
combinations += answer( l2 )
else:
# if the first tower is smaller than or equal to the other tower
# then we stop trying to make combinations
return combinations
l1 -= 1
l2 += 1
While this method does work for smaller numbers of bricks (returning 2 combinations for 5 blocks and 1 combination for 3 or 4 blocks), it does not work for much larger numbers that would be impossible to do on sheets of paper.
Wikipedia gives the generating function for the number of partitions of n with distinct parts as q(n) = product (1+x^k) for k=1..infinity. Given that you exclude the possibility of a single tower, the number of different valid tower arrangements is q(n)-1.
This gives this neat O(n^2) time and O(n) space program for counting tower arrangements.
def towers(n):
A = [1] + [0] * n
for k in xrange(1, n+1):
for i in xrange(n, k-1, -1):
A[i] += A[i-k]
return A[n] - 1
print towers(200)
The output is as required:
487067745
To understand the code, one can observe that A stores the first n+1 coefficients of the generating function product(1+x^k) for k=1...infinity. Each time through the k loop we add one more term to the product. We can stop at n rather than infinity, because subsequent terms of the product do not affect the first n+1 coefficients.
Another, more direct, way to think about the code is to define T(i, k) to be the number of tower combinations (including the single tower) with i blocks, and where the maximum height of any tower is k. Then:
T(0, 0) = 1
T(i, 0) = 0 if i > 0
T(i, k) = T(i, k-1) if i < k
= T(i, k-1) + T(i-k, k-1) if i >= k
Then one can observe that after j iterations of the for k loop, A contains the values of T(j, i) for i from 0 to n. The update is done somewhat carefully, updating the array from the end backwards so that results are changed only after they are used.
Imagine calling the function answer(6). Your code returns 2, the correct answer however is 3 (5, 1; 4, 2; 3, 2, 1). Why is this? your code stops when the amount of blocks above the bottom tower is greater than the length of the bottom tower, so it sees 3, 3 and stops, it therefor never considers the combination 3, 2, 1.
My advice would be to rethink the function, try to take into account the idea that you can stack a number of blocks N on top of a tower that is less than N high.

Multiples of 3 and 5 | Appending multiples to lists

I'v been studying Python for less than a month and am currently working on Project Euler.
So ironically I'm stuck on the first question. Check out my app road below and I would love some input as to where I have messed up. Or using the wrong logic.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
My Logic/Code Flow
sum = multiple_three + multiple_five
multiple_three = []
multiple_five = []
def multiple_three(bignumber):
for number in range(bignumber):
if number % 3 == 0:
multiple_three.append(number)
def multiple_five(bignumber):
for number in range(bignumber):
if number % 5 == 0:
multiple_five.append(number)
bignumber = 1000
multiple_five(bignumber)
multiple_three(bignumber)
print multiple_three
print multiple_five
Let's see.
We can start by using the fact that range has a step argument. So something like range(0,10,3) would get you 0,3,6,9.
So, for starters, we have
sum(range(0,1000,3)) + sum(range(0,1000,5))
But wait! Numbers divisible by 15 are divisible by both 5 and 3! We're counting them twice! Uh, uh, let's subtract them out
sum(range(0,1000,3)) + sum(range(0,1000,5)) - sum(range(0,1000,15))
Hum. I think we're still missing something here. Is there an easier way to add together an arithmetic progression? Could have sworn that there was...
something like (a_0 + a_n)*n/2, where n is the number of terms, maybe...
def sum_of_arithmetic_progression(start,stop,step):
n = (stop-start)//step #floor division :P
end = start + step*n
return (start + end)*n/2.0
sum_of_arithmetic_progression(0,1000,3)+sum_of_arithmetic_progression(0,1000,5)-sum_of_arithmetic_progression(0,1000,15)
This is what worked for me. Let me know if it worked for you too.
def multiples_of_3_or_5():
for number in xrange(1000):
if not number % 3 or not number % 5:
yield number
print sum(multiples_of_3_or_5())
You are not printing sum. But apart from that, you are counting numbers like 15 twice, i.e as a multiple of 3 as well as 5.
A quick solution would be to
print(sum(set(multiple_three+multiple_five)))
Here multiple_three+multiple_five gives a concatenated list. set identifies the unique elements, and sum will output the sum. Better would be to use "or"operator and append the numbers in a single loop as #Destry Amiott has suggested.

Project Euler #25: Keep getting Overflow error (result to large) - is it to do with calculating fibonacci number?

I'm working on solving the Project Euler problem 25:
What is the first term in the Fibonacci sequence to contain 1000
digits?
My piece of code works for smaller digits, but when I try a 1000 digits, i get the error:
OverflowError: (34, 'Result too large')
I'm thinking it may be on how I compute the fibonacci numbers, but i've tried several different methods, yet i get the same error.
Here's my code:
'''
What is the first term in the Fibonacci sequence to contain 1000 digits
'''
def fibonacci(n):
phi = (1 + pow(5, 0.5))/2 #Golden Ratio
return int((pow(phi, n) - pow(-phi, -n))/pow(5, 0.5)) #Formula: http://bit.ly/qDumIg
n = 0
while len(str(fibonacci(n))) < 1000:
n += 1
print n
Do you know what may the cause of this problem and how i could alter my code avoid this problem?
Thanks in advance.
The problem here is that only integers in Python have unlimited length, floating point values are still calculated using normal IEEE types which has a maximum precision.
As such, since you're using an approximation, using floating point calculations, you will get that problem eventually.
Instead, try calculating the Fibonacci sequence the normal way, one number (of the sequence) at a time, until you get to 1000 digits.
ie. calculate 1, 1, 2, 3, 5, 8, 13, 21, 34, etc.
By "normal way" I mean this:
/ 1 , n < 3
Fib(n) = |
\ Fib(n-2) + Fib(n-1) , n >= 3
Note that the "obvious" approach given the above formulas is wrong for this particular problem, so I'll post the code for the wrong approach just to make sure you don't waste time on that:
def fib(n):
if n <= 3:
return 1
else:
return fib(n-2) + fib(n-1)
n = 1
while True:
f = fib(n)
if len(str(f)) >= 1000:
print("#%d: %d" % (n, f))
exit()
n += 1
On my machine, the above code starts going really slow at around the 30th fibonacci number, which is still only 6 digits long.
I modified the above recursive approach to output the number of calls to the fib function for each number, and here are some values:
#1: 1
#10: 67
#20: 8361
#30: 1028457
#40: 126491971
I can reveal that the first Fibonacci number with 1000 digits or more is the 4782th number in the sequence (unless I miscalculated), and so the number of calls to the fib function in a recursive approach will be this number:
1322674645678488041058897524122997677251644370815418243017081997189365809170617080397240798694660940801306561333081985620826547131665853835988797427277436460008943552826302292637818371178869541946923675172160637882073812751617637975578859252434733232523159781720738111111789465039097802080315208597093485915332193691618926042255999185137115272769380924184682248184802491822233335279409301171526953109189313629293841597087510083986945111011402314286581478579689377521790151499066261906574161869200410684653808796432685809284286820053164879192557959922333112075826828349513158137604336674826721837135875890203904247933489561158950800113876836884059588285713810502973052057892127879455668391150708346800909439629659013173202984026200937561704281672042219641720514989818775239313026728787980474579564685426847905299010548673623281580547481750413205269166454195584292461766536845931986460985315260676689935535552432994592033224633385680958613360375475217820675316245314150525244440638913595353267694721961
And that is just for the 4782th number. The actual value is the sum of all those values for all the fibonacci numbers from 1 up to 4782. There is no way this will ever complete.
In fact, if we would give the code 1 year of running time (simplified as 365 days), and assuming that the machine could make 10.000.000.000 calls every second, the algorithm would get as far as to the 83rd number, which is still only 18 digits long.
Actually, althought the advice given above to avoid floating-point numbers is generally good advice for Project Euler problems, in this case it is incorrect. Fibonacci numbers can be computed by the formula F_n = phi^n / sqrt(5), so that the first fibonacci number greater than a thousand digits can be computed as 10^999 < phi^n / sqrt(5). Taking the logarithm to base ten of both sides -- recall that sqrt(5) is the same as 5^(1/2) -- gives 999 < n log_10(phi) - 1/2 log_10(5), and solving for n gives (999 + 1/2 log_10(5)) / log_10(phi) < n. The left-hand side of that equation evaluates to 4781.85927, so the smallest n that gives a thousand digits is 4782.
You can use the sliding window trick to compute the terms of the Fibonacci sequence iteratively, rather than using the closed form (or doing it recursively as it's normally defined).
The Python version for finding fib(n) is as follows:
def fib(n):
a = 1
b = 1
for i in range(2, n):
b = a + b
a = b - a
return b
This works when F(1) is defined as 1, as it is in Project Euler 25.
I won't give the exact solution to the problem here, but the code above can be reworked so it keeps track of n until a sentry value (10**999) is reached.
An iterative solution such as this one has no trouble executing. I get the answer in less than a second.
def fibonacci():
current = 0
previous = 1
while True:
temp = current
current = current + previous
previous = temp
yield current
def main():
for index, element in enumerate(fibonacci()):
if len(str(element)) >= 1000:
answer = index + 1 #starts from 0
break
print(answer)
import math as m
import time
start = time.time()
fib0 = 0
fib1 = 1
n = 0
k = 0
count = 1
while k<1000 :
n = fib0 + fib1
k = int(m.log10(n))+1
fib0 = fib1
fib1 = n
count += 1
print n
print count
print time.time()-start
takes 0.005388 s on my pc. did nothing fancy just followed simple code.
Iteration will always be better. Recursion was taking to long for me as well.
Also used a math function for calculating the number of digits in a number instead of taking the number in a list and iterating through it. Saves a lot of time
Here is my very simple solution
list = [1,1,2]
for i in range(2,5000):
if len(str(list[i]+list[i-1])) == 1000:
print (i + 2)
break
else:
list.append(list[i]+list[i-1])
This is sort of a "rogue" way of doing it, but if you change the 1000 to any number except one, it gets it right.
You can use the datatype Decimal. This is a little bit slower but you will be able to have arbitrary precision.
So your code:
'''
What is the first term in the Fibonacci sequence to contain 1000 digits
'''
from Decimal import *
def fibonacci(n):
phi = (Decimal(1) + pow(Decimal(5), Decimal(0.5))) / 2 #Golden Ratio
return int((pow(phi, Decimal(n))) - pow(-phi, Decimal(-n)))/pow(Decimal(5), Decimal(0.5)))
n = 0
while len(str(fibonacci(n))) < 1000:
n += 1
print n

Categories