Logic on printing Fibonacci numbers in Python - python

This is been killing me. When using the following code to print the Fib number, it gives the right output:
a = 0
n = 1
while n < 55:
print(n)
a,n = n,a+n
but when I change to this:
a = 0
n = 1
while n < 55:
print(n)
a = n
n = a+n
The output is totally different.
I've even run it thru pythontutor.com to watch stepping.
What are I missing.

There is a difference in the way variable values are interpreted and assigned between the two code snippets.
In case of the first snippet, while assigning the value to "n", the new value of a is not used, rather the value of a from the previous iteration is used.
But, in case of the second snippet, the value of "a" is first updated and then used for the second statement.
Let's take an example:
For the first iteration where n is 1,
First Code Snippet: At the end of the iteration, the value of a will be 1 and value of n also will be 1. (For n = a+n, value of a is considered 0)
Second Code Snippet: At the end of the iteration, the value of a will be 1 and value of n will be 2. (For n = a+n, value of a is considered 1)
The key point to be noted about the Python Comma Operator is that, all the expressions to the right of the assignment operator are evaluated first before the assignments are actually made and this causes the difference in output between the two.

Well, the initial assignment
a,n = n,a+n
means
old_a = a
a = n
n = old_a + n # saved a value (old_a) used
Please, notice that n = old_a + n, not a + n == 2 * n

Let's call a_i and n_i the values of a and n at the i-th iteration.
In the first code you are assigning to n_i+1 the value a_i + n_i, instead in the second code you are assignign to n_i+1 the value a_i+n_i+n_i.
This happen because you are assigning a before n in the second code, while this happen simultaneously in the first one. To solve this issue save in a temporary variable the old value of n or a.
Alternatively, with just a bit of math, you can do the following without saving any temporary variable:
a = 0
n = 1
while n < 55:
print(n)
n = a+n
a = n-a
which is equivalent to: a_i+1 = n_i+1 - a_i = a_i + n_i - a_i = n_i.

Related

Google foo.bar challenge "Hey I already did that", not passing all the test cases

This is the description of the problem I am trying to solve.
Hey, I Already Did That!
Commander Lambda uses an automated algorithm to assign minions randomly to tasks, in order to keep minions on their toes. But you've noticed a flaw in the algorithm -- it eventually loops back on itself, so that instead of assigning new minions as it iterates, it gets stuck in a cycle of values so that the same minions end up doing the same tasks over and over again. You think proving this to Commander Lambda will help you make a case for your next promotion.
You have worked out that the algorithm has the following process:
Start with a random minion ID n, which is a nonnegative integer of length k in base b
Define x and y as integers of length k. x has the digits of n in descending order, and y has the digits of n in ascending order
Define z = x - y. Add leading zeros to z to maintain length k if necessary
Assign n = z to get the next minion ID, and go back to step 2
For example, given minion ID n = 1211, k = 4, b = 10, then x = 2111, y = 1112 and z = 2111 - 1112 = 0999. Then the next minion ID will be n = 0999 and the algorithm iterates again: x = 9990, y = 0999 and z = 9990 - 0999 = 8991, and so on.
Depending on the values of n, k (derived from n), and b, at some point the algorithm reaches a cycle, such as by reaching a constant value. For example, starting with n = 210022, k = 6, b = 3, the algorithm will reach the cycle of values [210111, 122221, 102212] and it will stay in this cycle no matter how many times it continues iterating. Starting with n = 1211, the routine will reach the integer 6174, and since 7641 - 1467 is 6174, it will stay as that value no matter how many times it iterates.
Given a minion ID as a string n representing a nonnegative integer of length k in base b, where 2 <= k <= 9 and 2 <= b <= 10, write a function solution(n, b) which returns the length of the ending cycle of the algorithm above starting with n. For instance, in the example above, solution(210022, 3) would return 3, since iterating on 102212 would return to 210111 when done in base 3. If the algorithm reaches a constant, such as 0, then the length is 1.
My solution isn't passing 5 of the 10 test cases for the challenge. I don't understand if there's a problem with my code, as it's performing exactly as the problem asked to solve it, or if it's inefficient.
Here's my code for the problem. I have commented it for easier understanding.
def convert_to_any_base(num, b): # returns id after converting back to the original base as string
digits = []
while(num/b != 0):
digits.append(str(num % b))
num //= b
result = ''.join(digits[::-1])
return result
def solution(n, b):
minion_id_list = [] #list storing all occurrences of the minion id's
k = len(n)
while n not in minion_id_list: # until the minion id repeats
minion_id_list.append(n) # adds the id to the list
x = ''.join(sorted(n, reverse = True)) # gives x in descending order
y = x[::-1] # gives y in ascending order
if b == 10: # if number is already a decimal
n = str(int(x) - int(y)) # just calculate the difference
else:
n = int(x, b) - int(y, b) # else convert to decimal and, calculate difference
n = convert_to_any_base(n, b) # then convert it back to the given base
n = (k-len(n)) * '0' + n # adds the zeroes in front to maintain the id length
if int(n) == 0: # for the case that it reaches a constant, return 1
return 1
return len(minion_id_list[minion_id_list.index(n):]) # return length of the repeated id from
# first occurrence to the end of the list
I have been trying this problem for quite a while and still don't understand what's wrong with it. Any help will be appreciated.

How to add the last two elements in a list and add the sum to existing list

I am learning Python and using it to work thru a challenge found in Project Euler. Unfortunately, I cannot seem to get around this problem.
The problem:
Even Fibonacci numbers
Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will
be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.
I created a for loop that adds the second to last element and the last element from the list x:
x = [1,2]
for i in x:
second_to_last = x[-2]
running_sum = i + second_to_last
If you run the above, you get 3. I am looking to add this new element back to the original list, x, and repeat the process. However, each time I try to use the append() function, the program crashes and keeps on running without stopping. I tried to use a while loop to stop this, but that was a complete failure. Why am I not able to add or append() the new element (running_sum) back to the original list (x)?
UPDATE:
I did arrive at the solution (4613732), but I the work to getting there did not seem efficient. Here is my solution:
while len(x) in range(1,32):
for i in x:
second_to_last = x[-2]
running_sum = i + second_to_last
x.append(running_sum)
print(x)
new_x = []
for i in x:
if i%2 == 0:
new_x.append(i)
sum(new_x)
I did have to check the range to see visually whether I did not exceed 4 million. But as I said, the process I took was not efficient.
If you keep adding elements to a list while iterating over that list, the iteration will never finish.
You will need some other criterion to abort the loop - for example, in this case
if running_sum > 4000000:
break
would work.
(Note that you don't strictly speaking need a list at all here; I'd suggest experimenting a bit with it.)
Here are two different ways to solve this. One of them builds the whole list, then sums the even elements. The other one only keeps the last two elements, without making the whole list.
fib = [1,2]
while fib[-1] < 4000000:
fib.append(fib[-2]+fib[-1])
# Get rid of the last one, since it was over the limit.
fib.pop(-1)
print( sum(i for i in fib if i % 2 == 0) )
fib = (1,2)
sumx = 2
while True:
nxt = fib[0]+fib[1]
if nxt >= 4000000:
break
if nxt % 2 == 0:
sumx += nxt
fib = (fib[1],nxt)
print(sumx)
I don't answer your question about list modification but the solution for your problem:
def sum_even_number_fibonacci(limit):
n0 = 0 # Since we don't care about index (n-th), we can use n0 = 0 or 1
n1 = 1
even_number_sum = 0
while n1 <= limit:
if n1 % 2 == 0:
even_number_sum += n1
n2 = n0 + n1
# Only store the last two number of the Fibonacci sequence to calculate the next one
n0 = n1
n1 = n2
return even_number_sum
sum_even_number_fibonacci(4_000_000)

Breaking an iterative function in Python before a condition turns False

This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)

How to convert a collection of numbers into other base

Again firstly I am sorry because keep asking the same question.I am new to python programming. I am now trying to build a program which convert every element in a list of numbers of base 10 into its base 4. For example here, say i have numbers from 0 to 20 or more, I want to convert every number starting from 0 to numbers of base 4. The result should be like this
[[0,0],[0,1],...[1,1,0]
for numbers starting from 0 to 20. For the code,here is what I wrote so far
for n in range(21):
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print(base(n, 4))
For the result I got only for number 20 which is
[1,1,0]
Did I missed something here or there is another option to make it work?
Thank you for the answer
The issue is that you are defining the function inside the loop body, and only call it once. The structure you actually need is
<define the function>
for n in range(21):
print(base(n, 4))
The results will print out, but each one on a separate line. To create a list of the results you should replace the two lines of the loop with a single line that prints a list of all results, like
print([base(n, 4) for n in range(21)])
The problem is that you're defining the function inside the loop. What you want to do is define the function first, then construct your desired list:
def base(n,b):
result = []
while n > 0:
result.insert(0, n % b)
n = n // b
return result
print [base(n, 4) for n in range(21)]
(See this article if you're new to list comprehensions.)
If you want all the numbers, then indent your print statement, so that it's part of the loop.
If you want these as strings, then convert the digits to characters and concatenate them.
I've done both here:
def base(n, b):
result = []
while n > 0:
result.insert(0, n % b)
n = n / b
return result
for decimal in range(21):
print(''.join(str(digit) for digit in base(decimal, 4)))
You can manually compute the base of a number by doing something like this:
from math import log
from math import floor
def n_to_base(n, b):
num = n
lead_idx = floor(log(num, b))
b_rep = int(10**lead_idx)
b_rep = str(b_rep)
rep = 0
for i in range(len(b_rep)-1, -1, -1):
coeff = floor(num/(b**i))
rep += int(coeff*(10**i))
num -= int(coeff*(b**i))
return rep

SyntaxError: invalid syntax 11, 7, \t\t\tj++\n

I am not so proficient in python. I had this code in a practice coding. Since it is a golf code problem, i thought of trying python as i have some knowledge about it.
This is my program
Hack sequence of IndiaHacks-2014 if given as below
Hi = 2014*Hi-1 + 69*Hi-2 for (i>2)
Hi = 1 for (i<=2)
Given n, you need to find nth term of Hack sequence
I have used the following code
T = input()
for i in range(T):
N = int(input())
if N <= 2:
print 1
else :
a = [1,1]
j=2
while j < N :
a.append((2014 * a[j-1]) + (69 * a[j-2]))
j++
print a[N-1]
But i get the following error
SyntaxError:
invalid syntax
11, 7, \t\t\tj++\n
Can anyone please tell me what is wrong with this code and why am I getting this error?
Use j += 1 instead of j++. There is no ++ operator in python.
OR in this case simply don't use manually incremented loop variable:
T = input()
# I'm not sure about this part of your code:
# (indentation and the expected value of T)
for i in range(T):
N = int(input())
# To solve this problem you don't have to populate an array,
# you always need only the last two items:
prev2, prev1 = 1, 1
# We could omit this "if" check because the range(N-2) expression
# generates nothing when the input parameter is zero or less,
# that is: when N <= 2.
if N > 2:
# Note: in case of python3 use range(), in case of python2 use xrange()
for _ in range(N-2):
new = (2014 * prev1) + (69 * prev2)
prev2, prev1 = prev1, new
print prev1
To solve this problem you don't need an array but even if you needed an array you could run the j loop variable from 2 to N-1 with for j in range(2, N):. Note that in python you could simply use array[-1] and array[-2] to address the last two items of the array instead of calculating the absolute index (like array[N-1]). Python arrays can be indexed with a negative number relative to the end of the array.
There is no j++ in python. Use j += 1.

Categories

Resources