initialization in while loop - python

I'm new to python and having problem understanding the code snippet below.
I don't understand why sum is initialized to 0, not 1. Can anyone explain this initialization?
n = 4
sum = 0 # initialize sum
i = 1 # initialize counter
while i <= n:
sum = sum + i
i = i+1 # update counter
print("The sum is", sum)

This is actually more of a basics in computer programming than Python question. I'll try to explain in brief here.
Looks like your goal is to find the sum of integers 1 to n.
If you initialize the sum with 1, then the result you get will be always 1 more than the actual sum of integers 1 to n. You can verify that by doing runs with small values of n, say up to 5 and comparing the output you get with the actual sum. I'll put a table here for convenience:
n | sum(1, n)
-------------
1 | 1
2 | 3
3 | 6
4 | 10
5 | 15
Now compare this to the output when sum is initialized with 1. For curiosity's sake, you can play with initializing with other values too.

Sum is initialized to zero, but because the less than or equal to of n and i you always run at least one loop, take i = 1, then the sum is still one because the loop checks if 1 is less than or equal to 1 (i <= n). since it is then it adds i to the sum (ie. 1) making sum 1. it then updates i to 2 and goes to the top of the while loop. Since 2 <= 1 or i <= n is false here it breaks out and prints one as the sum

Related

How do i optimize this code to run for larger values? [duplicate]

This question already has answers here:
Elegant Python code for Integer Partitioning [closed]
(11 answers)
Closed 1 year ago.
I'm writing a python function that takes an integer value between 3 and 200 as input, calculates the number of sums using unique nonzero numbers that will equal the number and prints the output.
For example; with 3 as input 1 will be printed because only 1 + 2 will give 3, with 6 as input 3 will be printed because 1+2+3, 1+5 and 2+4 equal 6.
My code works well only for numbers less than 30 after which it starts getting slow. How do I optimize my code to run efficiently for all input between 3 and 200.
from itertools import combinations
def solution(n):
count = 0
max_terms = 0
num = 0
for i in range(1,n):
if num + i <= n:
max_terms += 1
num = num + i
for terms in range(2,max_terms + 1):
for sample in list(combinations(list(range(1,n)),terms)):
if sum(sample) == n:
count += 1
print(count)
Generating all combinations is indeed not very efficient as most will not add up to n.
Instead, you could use a recursive function, which can be called after taking away one partition (i.e. one term of the sum), and will solve the problem for the remaining amount, given an extra indication that future partitions should be greater than the one just taken.
To further improve the efficiency, you can use memoization (dynamic programming) to avoid solving the same sub problem multiple times.
Here is the code for that:
def solution(n, least=1, memo={}):
if n < least:
return 0
key = (n, least)
if key in memo: # Use memoization
return memo[key]
# Counting the case where n is not partitioned
# (But do not count it when it is the original number itself)
count = int(least > 1)
# Counting the cases where n is partitioned
for i in range(least, (n + 1) // 2):
count += solution(n - i, i + 1)
memo[key] = count
return count
Tested the code with these arguments. The comments list the sums that are counted:
print(solution(1)) # none
print(solution(2)) # none
print(solution(3)) # 1+2
print(solution(4)) # 1+3
print(solution(5)) # 1+4, 2+3
print(solution(6)) # 1+2+3, 1+5, 2+4
print(solution(7)) # 1+2+4, 1+6, 2+5, 3+4
print(solution(8)) # 1+2+5, 1+3+4, 1+7, 2+6, 3+5
print(solution(9)) # 1+2+6, 1+3+5, 2+3+4, 1+8, 2+7, 3+6, 4+5
print(solution(10)) # 1+2+3+4, 1+2+7, 1+3+6, 1+4+5, 2+3+5, 1+9, 2+8, 3+7, 4+6
your question isn't clear enough. So, I'm making some assumptionns...
So, what you want is to enter a number. say 4 and then, figure out the total combinations where two different digits add up to that number. If that is what you want, then the answer is quite simple.
for 4, lets take that as 'n'. 'n' has the combinations 1+3,2+2.
for n as 6, the combos are - 1+5,2+4,3+3.
You might have caught a pattern. (4 and 6 have half their combinations) also, for odd numbers, they have combinations that are half their previous even number. i.e. - 5 has (4/2)=2 combos. i.e. 1+4,2+3 so...
the formula to get the number for comnbinations are -
(n)/2 - this is if you want to include same number combos like 2+2 for 4 but, exclude combos with 0. i.e. 0+4 for 4
(n+1)/2 - this works if you want to exclude either the combos with 0 i.e. 0+4 for 4 or the ones with same numbers i.e. 2+2 for 4.
(n-1)/2 - here, same number combos are excluded. i.e. 2+2 wont be counted as a combo for n as 4. also, 0 combos i.e. 0+4 for 4 are excluded.
n is the main number. in these examples, it is '4'. This will work only if n is an integer and these values after calculations are stored as an integer.
3 number combos are totally different. I'm sure there's a formula for that too.

Find minimum steps required to reach n

I am trying to solve a Dynamic programming problem which is as follows but unable to solve it.
You are given a primitive calculator that can perform the following three operations with the current number đť‘Ą: multiply đť‘Ą by 2, multiply đť‘Ą by 3, or add 1 to đť‘Ą. Your goal is given a positive integer đť‘›, find the minimum number of operations needed to obtain the number đť‘› starting from the number 1
I found the solution on stackoverflow itself but unable to understand what's going on.
I have heard that every DP problem can be solved by creating matrix which I was trying to do but don't know where I am going wrong. The table is created below which shows number of steps required to reach to n from 1, initially I take values as infinity.
i / j 0 1 2 3 4 5
plus 1 0 1 2 3 4 5
multiple by 2 0 infinity 2 infinity 3 infinity
multiple by 3 0 infinity infinity 2 infinity infinity
I am trying to solve this problem in Python.
Can someone please help me.
I found the solution which is as follows but not able to understand exactly what is going on:
import math
target = int(input())
def optVal(target, cache):
result = [1] * cache[-1] # 1
for i in range(1, cache[-1]): # 2
result[-i] = target # 3
if cache[target-1] == cache[target] - 1: # 4
target -= 1
elif target % 2 == 0 and (cache[target // 2] == cache[target] - 1): # 5
target //= 2
else: # 6 # target % 3 == 0 and (cache[target // 3] == cache[target] - 1):
target //= 3
return result
cache = [0] + [math.inf] * target # 1
for i in range(1, len(cache)): # 2
temp1 = math.inf
temp2 = math.inf
temp3 = math.inf
temp1 = cache[i - 1] + 1
if i % 2 == 0:
temp2 = cache[i // 2] + 1
if i % 3 == 0:
temp3 = cache[i // 3] + 1
cache[i] = min(temp1, temp2, temp3)
print('Minimum operation: ', cache[target] - 1)
finalLst = optVal(target, cache)
print(' '.join([str(x) for x in finalLst]))
Input:
5
Output:
3
1245
This algorithm is split in two parts. The first is in the main, the second is in the optVal function.
The first part builds the cache list, where cache[i] holds the minimum number of steps necessary to arrive from 0 to i applying, at each step, one of the three possible operations: +1, *2 or *3. This list is the 1-dimensional case of the matrix you read about.
When cache[i] is calculated, all indices lower than i already have been calculated. One can get to i in three possible ways, so a maximum of three possible sources of i, i.e., elements of cache, need to be examined: i-1, i//2 and i//3, but i//2 only if i is even, and i//3 only if i can be divided by 3. These elements of cache are compared, and the content of the winner, incremented by 1 (because of the extra step to get to i), is stored in cache. This process is bootstrapped by putting a 0 in cache[0]. In the end, cache[target] will contain the minimum number of steps to get to target starting from 0 (which is 1 more than the steps to get there starting from 1, which is how the problem was stated – note that you only can apply the +1 operation to move out from 0).
Now, if I had written the code, I probably would have stored the “parent” or the “winning operation” of each cache[i] together with the number of steps to get there (BTW, those math.inf are not really needed, because there always is a finite number of steps to reach i, because of the +1 operation.) The approach of the author is to infer this information from the content of the possible parents (max 3) of each cache[i] that needs to be examined. In both cases, the chain of “ancestors” has to be reconstructed backwards, starting from cache[target], and this is what happens in optVal().
In optVal() the target is changed at each iteration (a bit confusingly), because at each iteration the info you have is the minimum number of steps needed to reach a certain target number. Knowing that, you look at the 1, 2 or 3 possible parents to check which one contains exactly that number of steps minus 1. The one that passes the test is the actual parent, and so you can continue building the chain backwards replacing target with the parent.
to solve this DP, you have to construct a table of minimum number of steps required to get n, if one two or all the operations were available. you will be creating it left to right, top to bottom, ie 1 to n, add 1 to mul 3. As you go down more number of operations are available
A cells value only depends on the value above it (if available) and atmax 3 values in the left side eg. for (n = 6),(mul 3) cell will depend only on (n = 6),(mul 2) and (n = 2)(mul 3), (n = 3)(mul 3), (n = 5)(mul 3). you will then compare these values and whichever is smaller after operation, you will put that value, so you will be comparing value of (n = 2)(mul 3) + 1 vs (n = 3)(mul 3) + 1 vs (n = 5)(mul 3) + 1 vs (n = 6)(mul 2), and then whichever is smaller you will put that value
since n = 1 is given, the first column would have all the values as zero
for n = 2, its values will depend on values of n = 1. you can "add 1" or "multiply by 2" (1 step), both are valid. so this column will have all the values as 0 + 1 = 1
for n = 3, its values will depend on values of n = 1 (because 1 = 1/3 of 3) AND n = 2. if you can only "add 1" or "multiply by 2", then you will choose to add 1 to n = 2 so total steps 1+1 = 2. BUT if you could also multiply by three you will need only one step so 0 + 1 = 1. since 1 < 2 you will put 1 as this value. so the entries for n = 3 is 2, 2, 1
for n = 4, it will depend on n = 3 (add 1), and n = 2 (mul 2). so the values will be 3, 2, 2
for n = 5, it will depend on n = 4 (add 1). so the values will be 4, 3, 3
so the minimum steps are 3 to reach n = 5
final table:
1 2 3 4 5
add 1 0 1 2 3 4
mul 2 0 1 2 2 3
mul 3 0 1 1 2 3
#include <bits/stdc++.h>
using namespace std;
int rec(vector<int> &dp,int n)
{
if(n==1) return 0;
if(dp[n]!=INT_MAX) return dp[n];
return dp[n]=min({1+rec(dp,n-1),(n%2==0)?1+rec(dp,n/2):INT_MAX,(n%3==0)?1+rec(dp,n/3):INT_MAX});
}
string genseq(vector<int> &dp, int n){
string res="";
while(n>1)
{
res=to_string(n)+" "+res;
if(dp[n-1]==(dp[n]-1)) n--;
else if(n%2==0&&( dp[n/2]==dp[n]-1)) n/=2;
else if(n%3==0&&( dp[n/3]==dp[n]-1)) n/=3;
}
return "1 "+res;
}
int main()
{
int n;
cin>>n;
vector<int> dp(n+1,INT_MAX);
dp[0]=0;
dp[1]=0;
std::cout << rec(dp,n) << std::endl;
std::cout << genseq(dp,n) << std::endl;
return 0;
}

Understanding recursion with the Fibonacci Series

I am trying to better understand recursion and how return statements work. As such, I'm looking at a piece of code meant to identify the fibonacci number associated with a given term -- in this case, 4. I'm have difficulty understanding the else statement.
def f(n):
if n == 0:
return 0
if n == 1:
return 1
else:
return f(n-1) + f(n-2)
f(4)
I have tried using Visualize Python to examine what happens at each step, but I get lost when it hits the else statement.
It looks like it is taking the value of n and subtracting 1, to create a new n value of 3 which it returns to the function definition. So it appears to only be returning the value from the first function in the else statement. However, the else statement is written to return the sum of 2 functions f(n-1) + f(n-2), in which case I thought the return value would be 5? Can you even add 2 functions together?
Thanks in advance for your help.
Here is a link to the code in Visualize Python Sum of 2 functions
When in doubt, just break it down.
The tree flow is actually counter-intuitive to the actual control flow, but once you understand the sequence of calls, it becomes clearer. The thing to understand here is that you keep breaking down a larger computation to a sum of smaller computations, and you stop when you hit the base case (the if statements). Now you can carry out all the small computations, and combining the results of those small computations to form a bigger, larger result, until you have your final answer.
Every time a recursive call hits the base case, it will return either 1, or 0, depending on what case was hit. This value will be returned to the previous caller. To understand, consider:
f(1)3 + f(0)3
Note here that the subscript represents the depth of the recursion call tree. The call is made by f(2)2. f(1)3 is computed first, and 1 is returned to f(2)2. f(0)3 is then computed, and 0 is returned to f(2)2. The two return values are summed, and the result is 1.
f(2)2 then returns 1 to whoever called it, which in this case happens to be f(3)1. f(3)1 called f(2)2 + f(1)2, meanwhile this other f(1)2 also returns 1 to f(3)1, who now adds that with the result of f(2)2, to form 2.
f(3)1 now passes 2 to f(4)0, its caller, which happened to call f(3)1 + f(2)1 ... and so it goes.
An alternative way of looking at this is to start from the first function call that is actually made: f(4)0.
f(4)0 computes f(3)1 + f(2)1. But to compute f(3)1, it needs to know f(2)2 + f(1)2, and similarly, to compute f(2)1, it needs to know f(1)2 + f(0)2, and so on.
Adding some print statements can also help clarifying the sequence:
def f(n):
print("Number received:", n)
if n == 0:
return 0
if n == 1:
return 1
else:
print("---- First recursion ----")
a = f(n-1)
print("---- Second recursion ----")
b = f(n-2)
print(" a=:",a,"; b=",b,"; returning:", a+b)
return a + b
print("Final f(4)=", f(4))
Output:
Number received: 4
---- First recursion ----
Number received: 3
---- First recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
a=: 1 ; b= 0 ; returning: 1
---- Second recursion ----
Number received: 1
a=: 1 ; b= 1 ; returning: 2
---- Second recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
a=: 1 ; b= 0 ; returning: 1
a=: 2 ; b= 1 ; returning: 3
Final f(4)= 3

Python find max number of combinations in binary

Hi I'm trying to figure out a function where given a length n of a list [x1, x2... xn], how many digits would be needed for a base 2 number system to assign a unique code to each value in the list.
For example, one digit can hold two unique values:
x1 0
x2 1
two digits can hold four:
x1 00
x2 01
x3 10
x4 11
etc. I'm trying to write a python function calcBitDigits(myListLength) that takes this list length and returns the number of digits needed. calcBitDigits(2) = 1, calcBitDigits(4) = 2, calcBitDigits(3) = 2, etc.
>>> for i in range(10):
... print i, i.bit_length()
0 0
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4
9 4
I'm not clear on exactly what it is you want, but it appears you want to subtract 1 from what bit_length() returns - or maybe not ;-)
On third thought ;-), maybe you really want this:
def calcBitDigits(n):
return (n-1).bit_length()
At least that gives the result you said you wanted in each of the examples you gave.
Note: for an integer n > 0, n.bit_length() is the number of bits needed to represent n in binary. (n-1).bit_length() is really a faster way of computing int(math.ceil(math.log(n, 2))).
Clarification: I understand the original question now ;-) Here's how to think about the answer: if you have n items, then you can assign them unique codes using the n integers in 0 through n-1 inclusive. How many bits does that take? The number of bits needed to express n-1 (the largest of the codes) in binary. I hope that makes the answer obvious instead of mysterious ;-)
As comments pointed out, the argument gets strained for n=1. It's a quirk then that (0).bit_length() == 0. So watch out for that one!
Use the following -
import math
int(math.ceil(math.log(x,2)))
where x is the list length.
Edit:
For x = 1, we need to have a separate case that would return 1. Thanks #thefourtheye for pointing this out.
I am not comfortable with the other answers, since most of them fail at the corner case (when n == 1). So, I wrote this based on Tim's answer.
def calcBitDigits(n):
if n <= 0: return 0
elif n <= 2: return 1
return (n-1).bit_length()
for i in range(10):
print i, calcBitDigits(i)
Output
0 0
1 1
2 1
3 2
4 2
5 3
6 3
7 3
8 3
9 4
x = int(log(n,2))+1
x will be the number of bits required to store the integer value n.
If for some reason you don't want to use .bit_length, here's another way to find it.
from itertools import count
def calcBitDigits(n):
return next(i for i in count() if 1<<i >= n)

Sum of all numbers

I need to write a function that calculates the sum of all numbers n.
Row 1: 1
Row 2: 2 3
Row 3: 4 5 6
Row 4: 7 8 9 10
Row 5: 11 12 13 14 15
Row 6: 16 17 18 19 20 21
It helps to imagine the above rows as a 'number triangle.' The function should take a number, n, which denotes how many numbers as well as which row to use. Row 5's sum is 65. How would I get my function to do this computation for any n-value?
For clarity's sake, this is not homework. It was on a recent midterm and needless to say, I was stumped.
The leftmost number in column 5 is 11 = (4+3+2+1)+1 which is sum(range(5))+1. This is generally true for any n.
So:
def triangle_sum(n):
start = sum(range(n))+1
return sum(range(start,start+n))
As noted by a bunch of people, you can express sum(range(n)) analytically as n*(n-1)//2 so this could be done even slightly more elegantly by:
def triangle_sum(n):
start = n*(n-1)//2+1
return sum(range(start,start+n))
A solution that uses an equation, but its a bit of work to arrive at that equation.
def sumRow(n):
return (n**3+n)/2
The numbers 1, 3, 6, 10, etc. are called triangle numbers and have a definite progression. Simply calculate the two bounding triangle numbers, use range() to get the numbers in the appropriate row from both triangle numbers, and sum() them.
Here is a generic solution:
start=1
n=5
for i in range(n):
start += len (range(i))
answer=sum(range(start,start+n))
As a function:
def trio(n):
start=1
for i in range(n):
start += len (range(i))
answer=sum(range(start,start+n))
return answer
def sum_row(n):
final = n*(n+1)/2
start = final - n
return final*(final+1)/2 - start*(start+1)/2
or maybe
def sum_row(n):
final = n*(n+1)/2
return sum((final - i) for i in range(n))
How does it work:
The first thing that the function does is to calculate the last number in each row. For n = 5, it returns 15. Why does it work? Because each row you increment the number on the right by the number of the row; at first you have 1; then 1+2 = 3; then 3+3=6; then 6+4=10, ecc. This impy that you are simply computing 1 + 2 + 3 + .. + n, which is equal to n(n+1)/2 for a famous formula.
then you can sum the numbers from final to final - n + 1 (a simple for loop will work, or maybe fancy stuff like list comprehension)
Or sum all the numbers from 1 to final and then subtract the sum of the numbers from 1 to final - n, like I did in the formula shown; you can do better with some mathematical operations
def compute(n):
first = n * (n - 1) / 2 + 1
last = first + n - 1
return sum(xrange(first, last + 1))

Categories

Resources