What is going wrong in this sum divisors program? [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 months ago.
Improve this question
function should return the sum of all the divisors of a number, without including it. A divisor is a number that divides into another without a remainder. so for this I have written below function in python.
def sum_divisors(n):
k = 1
sum = 0
while k < n :
if n % int(k) == 0:
print(k)
sum = sum + int(k)
k += 1
k = k + 1
# Return the sum of all divisors of n, not including n
return sum
print(sum_divisors(0)) # 0
print(sum_divisors(3)) # Should sum of 1 # total 1
print(sum_divisors(36))
print("----------") # Should sum of 1+2+3+4+6+9+12+18 # total 55
print(sum_divisors(102))
print("----------") # Should be sum of 2+3+6+17+34+51 # total 114
But I am getting o/p as --> 0 , 1 49, 112 respectively for above function.
after analysis I found that - value of "k" is not getting incremented inside if block as 2 and 4.
K value is comming as below for above four functioned when getting called-->
0
----------
1
1 --> it should be 2
----------
1 --> after 1 next should come as 2 , as 36 is divisible by 2
3 --> after 3 next should come as 4 , as 36 is divisible by 4, but it is missing
6
9
12
18
49
----------
1 --> after 1 next should come as 2 , as 102 is divisible by 2
3
6
17
34
51
112
so can anyone please tell what is going wrong above. If possible you can suggest any alternate method to optimize above program.

You're incrementing k twice, once conditionally inside the if, once unconditionally outside it, so you can never find adjacent factors. Remove the one inside the if.
Better, just replace it with a for+range loop and stop managing k manually:
def sum_divisors(n):
sum = 0
for k in range(1, n):
if n % k == 0: # No need to int-ify k, it's always an int anyway
print(k)
sum += k # Can use += to avoid repetition, and k is an int already
# Return the sum of all divisors of n, not including n
return sum
If the print is purely for debugging and can be removed, this simplifies to a one-liner, with the optimized sum function + a generator expression:
def sum_divisors(n):
return sum(k for k in range(1, n) if n % k == 0)

you only have to comment the first addition of k :
it is as if you're incrementing it twice so you're jumping on numbers to test on.
def sum_divisors(n):
k = 1
sum = 0
while k < n :
if n % int(k) == 0:
# print(k)
sum = sum + int(k)
# k += 1
k = k + 1
# Return the sum of all divisors of n, not including n
return sum
print(sum_divisors(0)) # 0
print(sum_divisors(3)) # Should sum of 1 # total 1
print(sum_divisors(36))
print("----------") # Should sum of 1+2+3+4+6+9+12+18 # total 55
print(sum_divisors(102))
print("----------") # Should be sum of 2+3+6+17+34+51 # total 114

You have both k += 1 and k = k + 1 inside your loop, so that means that you add 2 for every iteration.
This code:
def sum_divisors(n):
k = 1
sum = 0
while k < n :
if n % int(k) == 0:
print(k)
sum = sum + int(k)
k = k + 1
# Return the sum of all divisors of n, not including n
return sum
print(sum_divisors(0)) # 0
print("----------")
print(sum_divisors(3)) # Should sum of 1 # total 1
print("----------")
print(sum_divisors(36))
print("----------") # Should sum of 1+2+3+4+6+9+12+18 # total 55
print(sum_divisors(102))
print("----------") # Should be sum of 2+3+6+17+34+51 # total 114
Gives this output:
0
----------
1
1
----------
1
2
3
4
6
9
12
18
55
----------
1
2
3
6
17
34
51
114
----------

You have to use "else" for k = k + 1
def sum_divisors(n):
k = 1
sum = 0
print(n)
while k < n :
if n % k == 0:
print(k)
sum = sum + k
k += 1
else:
k = k + 1
return sum

Related

How can i calculate and print the sum of first N elements of below sequence using recursive function

How can i calculate and print the sum of first N elements of below sequence using recursive function
Example:
Sample Input N: 4
Sample Output: 7 + 12 + 17 + 22 = 58
I did some part of the code but it gives wrong result and I don't know where I'm making mistakes. That's why I need help!
def recur_sum(n):
if n <= 1:
return n
else:
for i in range(7,n+1):
return i + recur_sum(i-1)
num = int(input("Enter a number: "))
if num < 0:
print("Enter a positive number")
else:
print("The sum is",recur_sum(num))
As far as I understand your question, you want the sum of a sequence which each element of this sequence is increased by a step (such as 5), and it has an initial value (like 7), and you want the sum of first N (like 4) elements of this sequence.
At each recursion level, we add the current value to step , but when n == 1 we only return the current value (which is the Nth item of the sequence).
Do this:
def recur_sum(cur_val, step, n):
if n == 1:
return cur_val
return cur_val + recur_sum(cur_val+step,step,n-1)
num = int(input("Enter a number: "))
init_val = 7
step = 5
if num < 0:
print("Enter a positive number")
else:
print("The sum is",recur_sum(init_val, step, num))
Output:
The sum is 58
this returns a list of all sequential numbers starting at 7 each increment of 5. sum the return array.... change 5 and 2 to change increments for desired jumps/steps, and change the initial return value..
def recur_sum(n):
if n == 1:
return [7]
else:
return [5*n+2] + recur_sum(n-1)
num = int(input("Enter a number: "))
res = recur_sum(num)
print(sum(res))
A recursive function which returns all the elements up to n (where n is the input of your function) has already been proposed above.
In my understanding, you want a function with some recursive logic that return the sum of all the elements up to the n-th.
Your sequence is 7, 12, 17, 22, 27 and so forth. If we disect it:
it element sum sum is element is
1 7 7 1 * 7 + 0 * 5 1 * 7 + 0 * 5
2 12 19 2 * 7 + 1 * 5 1 * 7 + 1 * 5
3 17 36 3 * 7 + 3 * 5 1 * 7 + 2 * 5
4 22 58 4 * 7 + 6 * 5 1 * 7 + 3 * 5
5 27 85 5 * 7 + 10 * 5 1 * 7 + 4 * 5
If you want at any cost to implement a recursive solution, if is evident that at each step you need to increase the rolling sum by it * 7 + (it - 1) * 5 (where 7 is your start point, while 5 is your step).
You can implement a recursive solution as follows:
def recursive(n, step = 5, start = 7, counter = 1):
if n > 0:
this_element = start + (counter - 1) * step
if counter == n:
return this_element
else:
return this_element + recursive(n, step = step, start = start, counter = counter + 1)
else:
return 0
for i in range(1, 10):
print(recursive(i))
OUTPUT
7
19
36
58
85
117
154
196
243
From the table above you can see though that maybe a recursive solution is overkilling here given that the sum of elements up to n-th step has solution:
def my_sum(n, step = 5, start = 7):
return n * start + int(step * (n - 1) * n / 2)
for i in range(1, 10):
print(my_sum(i))
OUTPUT
7
19
36
58
85
117
154
196
243

Why does program count one extra value (cycle "while")?

Why the program count one more value? For example, I give him N = 50. It gives out:
1
4
9
16
25
36
49
64
Code:
N = int(input())
n = 1
k = 1
while n < N:
n = k ** 2
print(n)
k = k + 1
As explained, you're checking n then changing n, you want to change n then check before continuing.
You can use the walrus operator to assign n and check it's value all in the while statement. (requires Python 3.8+)
N = int(input())
n = 1
k = 1
while (n := k**2) < N:
print(n)
k += 1
This essentially assigns n to k**2 then checks if that result is <N before continuing.
1
4
9
16
25
36
49
Your program outputs 1 4 9 16 25 36 49 64 if your input is 50 because the `while`` loop is checking the value before you increase it. Once in the loop, you increase it, calculate the square and then print.
If you want it to terminate, try setting calculating n as the last step in the loop:
N = int(input())
n = 1
k = 1
while n < N:
print(n)
k = k + 1
n = k ** 2
You're checking whether you reached the limit before you calculate the square and print it. So you're checking the previous value of n, not the one that's about to be printed.
Move the check inside the loop.
while True:
n = k ** 2
if n >= N:
break
print(n)
k += 1
The n < N is evaluated after you've changed (and printed) n.
n = 1
k = 1
N=50
while 1:
n = k ** 2
if n > N:
break
print(n)
k = k + 1
To fix this, break before you print, moving the evaluation inside the loop rather than after the last update of n
1
4
9
16
25
36
49
With the condition of your code, for example, when n = 49, The condition is fulfilled because 49 < 50 therefore it will continue to process the value and print the new one. But once n = 64 which is > 50, it stops. This is a possible solution:
N = int(input())
n = 1
k = 1
while True:
if n >= N:
break
n = k ** 2
print(n)
k = k + 1
This will continuously execute the code but once the condition is met that n >= N, it will stop executing.

A test interview question I could not figure out

So I wrote a piece of code in pycharm
to solve this problem:
pick any 5 positive integers that add up to 100
and by addition,subtraction or just using one of the five values
you should be able to make every number up to 100
for example
1,22,2,3,4
for 1 I could give in 1
for 2 i could give in 2
so on
for 21 I could give 22 - 1
for 25 I could give (22 + 2) - 1
li = [1, 1, 1, 1, 1]
lists_of_li_that_pass_T1 = []
while True:
if sum(li) == 100:
list_of_li_that_pass_T1.append(li)
if li[-1] != 100:
li[-1] += 1
else:
li[-1] = 1
if li[-2] != 100:
li[-2] += 1
else:
li[-2] = 1
if li[-3] != 100:
li[-3] += 1
else:
li[-3] = 1
if li[-4] != 100:
li[-4] += 1
else:
li[-4] = 1
if li[-5] != 100:
li[-5] += 1
else:
break
else:
if li[-1] != 100:
li[-1] += 1
else:
li[-1] = 1
if li[-2] != 100:
li[-2] += 1
else:
li[-2] = 1
if li[-3] != 100:
li[-3] += 1
else:
li[-3] = 1
if li[-4] != 100:
li[-4] += 1
else:
li[-4] = 1
if li[-5] != 100:
li[-5] += 1
else:
break
this should give me all the number combinations that add up to 100 out of the total 1*10 ** 10
but its not working please help me fix it so it prints all of the sets of integers
I also can't think of what I would do next to get the perfect sets that solve the problem
After #JohnY comments, I assume that the question is:
Find a set of 5 integers meeting the following requirements:
their sum is 100
any number in the [1, 100] range can be constructed using at most once the elements of the set and only additions and substractions
A brute force way is certainly possible, but proving that any number can be constructed that way would be tedious. But a divide and conquer strategy is possible: to construct all numbers up to n with a set of m numbers u0..., um-1, it is enough to build all numbers up to (n+2)/3 with u0..., um-2 and use um-1 = 2*n/3. Any number in the ((n+2)/3, um-1) range can be written as um-1-x with x in the [1, (n+2)/3] range, and any number in the (um-1, n] range as um-1+y with y in the same low range.
So we can use here u4 = 66 and find a way to build numbers up to 34 with 4 numbers.
Let us iterate: u3 = 24 and build numbers up to 12 with 3 numbers.
One more step u2 = 8 and build numbers up to 4 with 2 numbers.
Ok: u0 = 1 and u1 = 3 give immediately:
1 = u0
2 = 3 - 1 = u1 - u0
3 = u1
4 = 3 + 1 = u1 + u0
Done.
Mathematical disgression:
In fact u0 = 1 and u1 = 3 can build all numbers up to 4, so we can use u2 = 9 to build all numbers up to 9+4 = 13. We can prove easily that the sequence ui = 3i verifies sum(ui for i in [0, m-1]) = 1 + 3 + ... + 3m-1 = (3m - 1)/(3 - 1) = (um - 1) / 2.
So we could use u0=1, u1=3, u2=9, u3=27 to build all numbers up to 40, and finally set u4 = 60.
In fact, u0 and u1 can only be 1 and 3 and u2 can be 8 or 9. Then if u2 == 8, u3 can be in the [22, 25] range, and if u2 == 9, u3 can be in the [21, 27] range. The high limit is given by the 3i sequence, and the low limit is given by the requirement to build numbers up to 12 with 3 numbers, and up to 34 with 4 ones.
No code was used, but I think that way much quicker and less error prone. It is now possible to use Python to show that all numbers up to 100 can be constructed from one of those sets using the divide and conquer strategy.

How do I reduce the number of loops or complexity

So what I am trying to do is to find count of alternating numbers such that it alternates with -ve and positive sign
for eg: 1 -2 3 -4 would get me 4 3 2 1 as from 1 to -4 including the two numbers there are 4 numbers.
Simillarly for 1 1 -3 2 would get me 1 3 2 1
Now I have the code but I cannot optimise it and it returns me a time limit exceeded error even though it works for moderate input stream.
j=0
count=0
length=(raw_input())
st=map(int,raw_input().split())
while j+1 < len(st):
k=j+1
count=0
temp=j
while k<len(st) and ((st[k]<0 and st[j]>0) or (st[k]>0 and st[j]<0)):
count+=1
k+=1
j+=1
print count+1,
j=temp+1
print 1
Try using for loops instead of while loops as that avoids you some variable assignments:
st = map(int, raw_input().split())
length = len(st)-1
for i in range(length):
count = 1
for j in range(i, length):
if (st[j]<0 and st[j+1]>0) or (st[j+1]<0 and st[j]>0):
count += 1
else:
break
print(count)
print(1)
This will give:
<< 1 -2 3 4
>> 4
>> 3
>> 2
>> 1
<< 1 1 -3 2
>> 1
>> 3
>> 2
>> 1
It may also be a bit faster if you extract the numbers from the list once instead of twice:
st = map(int, raw_input().split())
length = len(st)-1
for i in range(length):
count = 1
for j in range(i, length):
first, second = st[j:j+2]
if (first<0 and second>0) or (first>0 and second<0):
count += 1
else:
break
print(count)
print(1)
The last thing I would try is checking that they sigs are different with a single comparisson but I do not really expect this to be faster:
st = map(int, raw_input().split())
length = len(st)-1
for i in range(length):
count = 1
for j in range(i, length):
product = st[j] * st[j+1]
if product != abs(product):
count += 1
else:
break
print(count)
print(1)

Prime Factorization [duplicate]

This question already has answers here:
Prime factorization - list
(17 answers)
Closed 6 years ago.
So my program is supposed to find the prime factors of an integer and then the contents of the integer array is printed out and the values in the array are supposed to be multiplied together (giving you the original number)
this is what it is supposed to look like
Prime Factorization Program
Enter an integer > 1: 210
Prime Factors
2
3
5
7
Check Product = 210
this is my code and my results
def main():
a = [0]*20
print("Prime Factorization Program")
print()
num = eval(input("Enter an integer > 1: "))
count = 0
for k in range(1,num):
if num % k == 0:
a[count]= k
count = count + 1
mySum = 0
for k in range(count):
mySum = mySum + a[k]
print()
print("Prime Factors")
for k in range(count):
print(a[k])
print("Check Product =",mySum)
main()
here are my result
Prime Factorization Program
Enter an integer > 1: 210
Prime Factors
1
2
3
5
6
7
10
14
15
21
30
35
42
70
105
Check Product = 366
Problem - If f is a factor, you don't want to count multiples of f.
Solution - Once you identify a factor f, divide n by f.
Example - 210 is divisible by 2; divide by 2 and thereafter process 105. That ensures you don't count any more multiples of 2 like 6 or 10. 105 is divisible by 3; divide by 3 and continue with 35.
Problem - Prime factors can show up multiple times. 12 = 2×2×3.
Solution - If f is a factor, keep checking for it and dividing by f until you've accounted for all occurrences.
Example - 12 is divisible by 2; divide by 2 to get 6. 6 is still divisible by 2; divide by 2 again to get 3. 3 is not divisible by 2; continue to the next factor.
Because your code is printing all the factor instead of just prime factors. Below is the sample function you may refer for prime factorization:
def prime_factors(n):
prim_facs = []
d = 2
while d*d <= n:
while (n % d) == 0:
prim_facs.append(d)
n //= d
d += 1
if n > 1:
prim_facs.append(n)
return prim_facs
# Sample Example
# >>> prime_factors(210)
# [2, 3, 5, 7]

Categories