sum digits (python simple) - python

I wanted to write a program which adds the digits until it becomes a single digit number, here is my code
n=int(input(""))
b=10**18
while not 1<=n<=b:
n=int(input(""))
else:
tot=0
while(n!=0):
dig=n%10
tot=tot+dig
n=n//10
s=0
if tot>=10:
while (tot!=0):
tot2=tot%10
s=s+tot2
tot=tot//10
else:
s=tot
print(s)
I thinked that it works correctly but when I type 88888888888 it gives me 16 as output not 7 ...but every thing is correct ...How can I fix that?

You can simply do
s = n % 9
Because from math we know that sum of digits of any number and a number itself has the same remainder when divided by 9. The only corner case is when n is divisible 9, in this case, you want s=9.
The final code would be:
n=int(input())
b=10**18
while not 1 <= n <= b:
n=int(input())
if (n%9 == 0):
s = 9
else:
s = n % 9

You could approach this recursively.
def sumDigits(N): return N if N<10 else sumDigits(sum(divmod(N,10)))
sumDigits(88888888888) # 7
If you want a mathematical solution:
def sumDigits(N): return (N+8)%9+1

the problem is simple that you don't do enough iterations, as Daniyar Aubekerov commented you need 3 round for 88888888888 (88888888888->88->16->7 ) but you only do 2
one way to solve it is simple factor out the commons parts into their own functions and use them as needed, for example
def digits(n):
"digits of the number n"
dig = []
while n>0:
n,d = divmod(n,10) # this do both n//10 and n%10
dig.append(d)
return dig
def sum_digits(n):
s = sum(digits(n)) #sum add together all the elements in the list
while s>10:
s = sum(digits(s))
return s
or even more simple, use a more direct approach to get it, as this is also know as the digital root of the number
def digital_root(n):
if n==0:
return 0
else:
return 1 + (n-1)%9
and some quick test
>>> digits(100)
[0, 0, 1]
>>> digits(88888888888)
[8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]
>>> sum_digits(88888888888)
7
>>> digital_root(88888888888)
7
>>>

Related

go through each number between 1 and the number input until it finds a factor and adds it to a list

def factorList(num):
listOfFactors = []
for i in range <= num:
if num / i == 0:
listOfFactors.append(i)
print(listOfFactors)
factorList(36)
I want the function to go through each number between 1 and the number input until it finds a factor and adds it to a list
range() is a function (it needs parens), and it starts at zero, rather than 1...
You seem to have tried to combine range with a while loop logic, like so
i = 1
while i <= num:
# if ... append ...
i += 1
But you can do the same with list-comprehension
def factorList(num):
return [i for i in range(1, num+1) if num % i == 0]
print(factorList(36))
Output
[1, 2, 3, 4, 6, 9, 12, 18, 36]
side-note: For factorization, you only need to loop up to the square-root of the number.
range() is a function that returns a sequence of numbers, so you need to call it like a function.
for i in range(num):
See some documentation here: https://www.w3schools.com/python/ref_func_range.asp

Python printing many times over for single print

My code is:
for n in range(1,10000000):
if n>1:
for i in range(2,n):
if n % i == 0:
break
else:
v = 2+n
for i in range(2,v):
if v % i == 0:
break
else:
print(n,v)
When I run the code, it prints multiple of each number with each having a random number of the particular two numbers. I am having trouble fixing the code. I have asked others who are more well-versed in coding than I am, but they were unable to solve the problem. Help would be greatly appreciated. Thank you!
The output is not random, but as the desired output is not defined, I'll start with explaining what the current algorithm actually does;
The code can be split in to two main functionalities. The first functionality looks for a prime number n. If n is not prime, the code continues to the next n:
for n in range(1,10000000):
if n>1:
for i in range(2,n):
if n % i == 0:
break
The second functionality comes into play only if n is prime (a clever use of for..else). It will now check to see if n+2 is divisible by any number from 2 up to n+1. I took the liberty of replacing v with n+2 in the following snippet, as I believe it makes things a bit clearer;
else:
#v = 2+n # taking liberty..
for i in range(2, n+2):
if (n+2) % i == 0:
break
else:
print(n, n+2)
To illustrate what actually happens, I chose primes 5, 7, 11, and 23, as I believe these four can explain the output pretty well. Starting with 5:
for i in range(2, 7): # i -> [2, 3, 4, 5, 6]
if (7) % i == 0:
break
else:
print(5, 7)
In the snippet above, 5 7 will be printed 5 times, once for each i in the loop, as 7 is a prime and is not divisible by any given i.
for i in range(2, 9): # i -> [2, 3, 4, 5, 6, 7, 8]
if (9) % i == 0:
break
else:
print(7, 9)
Here you will find that 7 9 is only printed once, because 9 is not divisible by 2, but it is divisible by 3 - in which case, the loop breaks, and continues to the next prime n. Now let's look at n=11:
for i in range(2, 13): # i -> [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
if (13) % i == 0:
break
else:
print(11, 13)
Here, like with n=5, n+2 is also prime (13). As it is not divisible by any number in i, the sequence 11 13 will be printed the length of i, which is 11 (it will always be n, as we start from 2, and add 2 to n).
for i in range(2, 25): # i -> [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
if (25) % i == 0:
break
else:
print(23, 25)
This is the first interesting case in the realm of lower numbers. Up to 23, all n+2 were either prime, or divisible by 3; they were printed n times, or just once. With n=23, the sequence 23 25 is printed 3 times, because 25 is not divisible by 2, 3, or 4 (3 prints), but it is divisible by 5, so now the loop breaks again, and continues to the next prime n.
Again, the resulting output you are looking for is not clear, but reading through previous comments I have to warn - this solution will not print two prime numbers separated by 2 (as #alani figured), it will simply ensure each line is printed just once:
for n in range(3,10000000):
for i in range(2,n):
if n % i == 0:
break
else:
v = 2+n
for i in range(3,v):
if v % i:
print(n,v)
break
I made it so it'll only print once each time, along with only going to the square root of each number as going past that is overkill
for n in range(2,10000000): #started at 2 instead of 1
#removed if statement because i changed start from 1 to 2
for i in range(2,int(n**0.5) + 2): #now goes to square root plus 1(to correct for automatic rounding down)
if n % i == 0:
break
else:
v = n + 2
for f in range(2,int(v**0.5) + 2): #now goes to square root plus 1(to correct for automatic rounding down)
if v % f == 0:
break
elif f == int(v**0.5) + 1: #changed else to elif with condition of being at last iterated integer
print(n,v)
I didn't want to totally revamp your code but if you do want to make this more efficient, i would recommend creating a list of prime numbers you find(by appending each time you find one) and then using a for loop iterating over the list up to the square root of the current value(as iterating over composite numbers is inefficient, since they are multiples of the prime numbers)
Hopefully this is what you wanted, if not i can try to help further though, also please don't take my recommendation as criticism or anything, it's just my opinion on what might make your code run faster

Google Foobar - Please Pass The Coded Message Test Case Failure

Question
You have L, a list containing some digits (0 to 9). Write a function solution(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3.
If it is not possible to make such a number, return 0 as the solution. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
Test Cases
Input:
solution.solution([3, 1, 4, 1])
Output:
4311
Input:
solution.solution([3, 1, 4, 1, 5, 9])
Output:
94311
My code
def sum(L):
totalSum = 0
for x in range(len(L)):
totalSum = totalSum + L[x]
return totalSum
def listToInteger(L):
strings = [str(integer) for integer in L ]
concatString = "".join(strings)
finalInt = int(concatString)
return finalInt
def solution(L):
num = sum(L)
if not num % 3:
L.sort(reverse=True) # sort list in descending order to create largest number
return listToInteger(L)
else:
n = num % 3
flag = False
while not flag: # locate digit causing indivisiblity
if n in L:
L.remove(n)
L.sort(reverse=True)
return listToInteger(L)
elif(n > num):
return 0
else:
n += 3
I get the two test cases correct, but there is one hidden case that keeps failing. I'm not sure if the input is not strict enough, or if there is a fault in my logic
the only fault in logic I can think of is if the input was [8,5,3] , the sum would be 16 and 16 % 3 = 1
so it would check the list for 1, 4, 7, 10, 13 , 16 but it wouldnt be in the list so it wouldn't remove 8 or 5. it would return 0 when it should actually return [3].
I added a function for this but even then it was still failing the hidden test case. . .
Any suggestions would be appreciated
Your code seems to assume that there can only be one digit that is wrong. What would you do with input like 1,1,3? sum is 5, n is 2 and you'll try to remove 2, 5, and then fail and return 0.
You need to change your assumptions and check other digits too, and make it possible to remove more than 1 digit when working toward a solution.
This code worked fine for [8,5,3]
example: [8,5,3,6]
sum will be 22
sum%3 will be 1
so numbers need to check in list to delet are 1,4 7,10,13,16,19,22 and it will never delet any elements,since there are no these elements in the list
so still there are 6 and 3 which can be multilple of 3.
so take 3 and 6 in a list and sort them and answer will be 63
def sum(L):
totalSum = 0
for x in range(len(L)):
totalSum = totalSum + L[x]
return totalSum
def listToInteger(L):
strings = [str(integer) for integer in L ]
concatString = "".join(strings)
finalInt = int(concatString)
return finalInt
def solution(L):
num = sum(L)
if not num % 3:
L.sort(reverse=True) # sort list in descending order to create largest number
return listToInteger(L)
else:
n = num % 3
flag = False
while not flag: # locate digit causing indivisiblity
if n in L:
L.remove(n)
L.sort(reverse=True)
return listToInteger(L)
elif(n > num):
k=[]
for i in L:
if i%3==0:
k.append(i)
if len(k)!=0:
k.sort(reverse=True)
return listToInteger(k)
else:
return 0
else:
n += 3
l=[8,5,3]
print(solution(l))

Google Foobar Question - Please Pass The Coded Message

Google Foobar Question:
Please Pass the Coded Messages
You need to pass a message to the bunny prisoners, but to avoid detection, the code you agreed to use is... obscure, to say the least. The bunnies are given food on standard-issue prison plates that are stamped with the numbers 0-9 for easier sorting, and you need to combine sets of plates to create the numbers in the code. The signal that a number is part of the code is that it is divisible by 3. You can do smaller numbers like 15 and 45 easily, but bigger numbers like 144 and 414 are a little trickier. Write a program to help yourself quickly create large numbers for use in the code, given a limited number of plates to work with.
You have L, a list containing some digits (0 to 9). Write a function answer(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3. If it is not possible to make such a number, return 0 as the answer. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
Languages
To provide a Python solution, edit solution.py
To provide a Java solution, edit solution.java
Test cases
Inputs:
(int list) l = [3, 1, 4, 1]
Output:
(int) 4311
Inputs:
(int list) l = [3, 1, 4, 1, 5, 9]
Output:
(int) 94311
Use verify [file] to test your solution and see how it does. When you are finished editing your code, use submit [file] to submit your answer. If your solution passes the test cases, it will be removed from your home folder.
So that's the question, my python code only passes 3 out of 5 tests cases. I spent a few hours but can't find out what cases I am missing. Here is my code:
maximum = [0, 0, 0, 0, 0,0,0,0,0]
def subset_sum(numbers, target, partial=[]):
global maximum
s = sum(partial)
if s%3 == 0:
if s != 0:
str1 = ''.join(str(e) for e in partial)
y = int(str1)
str1 = ''.join(str(e) for e in maximum)
z = int(str1)
if y>z:
maximum = partial
# print maximum
if s >= target:
return # if we reach the number why bother to continue
for i in range(len(numbers)):
n = numbers[i]
remaining = numbers[i+1:]
subset_sum(remaining, target, partial + [n])
def answer(l):
global maximum
#maximum = [0, 0, 0, 0, 0]
subset_sum(l,sum(l))
maximum = sorted(maximum, key=int, reverse=True)
str1 = ''.join(str(e) for e in maximum)
y = int(str1)
return y
print(answer([3,1,4,1,5,9]))
So what test cases am I not accounting for, and how could I improve it?
try this using combination it may help:
from itertools import combinations
def answer(nums):
nums.sort(reverse = True)
for i in reversed(range(1, len(nums) + 1)):
for tup in combinations(nums, i):
if sum(tup) % 3 == 0: return int(''.join(map(str, tup)))
return 0
Presently, you are forming a number by using adjacent digits only while the question does not say so.
A quick fix would be to set remaining list properly -
remaining = numbers[:i] + numbers[i+1:]
But you need to think of better algorithm.
Update
inputNumbers = [2, 1, 1, 1, 7, 8, 5, 7, 9, 3]
inputNumSorted = sorted(inputNumbers)
sumMax = sum(inputNumbers)
queue = [(sumMax, inputNumSorted)]
found = False
while (len(queue) > 0):
(sumCurrent, digitList) = queue.pop()
remainder = sumCurrent%3
if (remainder == 0):
found = True
break
else :
for index, aNum in enumerate(digitList):
if(aNum%3 == remainder):
sumCurrent -= remainder
digitList.remove(aNum)
found = True
break
else:
newList = digitList[:index]+digitList[index+1:]
if (len(newList) > 0):
queue.insert(0, (sumCurrent-aNum, newList))
if(found):
break
maxNum = 0
if (found):
for x,y in enumerate(digitList):
maxNum += (10**x)*y
print(maxNum)
I believe the solution looks something like this:
Arrange the input digits into a single number, in order from largest to smallest. (The specific digit order won't affect its divisibility by 3.)
If this number is divisible by 3, you're done.
Otherwise, try removing the smallest digit. If this results in a number that is divisible by 3, you're done. Otherwise start over with the original number and try removing the second-smallest digit. Repeat.
Otherwise, try removing digits two at a time, starting with the two smallest. If any of these result in a number that is divisible by 3, you're done.
Otherwise, try removing three digits...
Four digits...
Etc.
If nothing worked, return zero.
Here's the actual solution and this passes in all the test cases
import itertools
def solution(l):
l.sort(reverse = True)
for i in reversed(range(1, len(l) + 1)):
for j in itertools.combinations(l, i):
if sum(tup) % 3 == 0: return int(''.join(map(str, j)))
return 0
Here is a commented solution (that passed all test cases):
def solution(l):
# sort in decending order
l = sorted(l, reverse = True)
# if the number is already divisible by three
if sum(l) % 3 == 0:
# return the number
return int("".join(str(n) for n in l))
possibilities = [0]
# try every combination of removing a single digit
for i in range(len(l)):
# copy list of digits
_temp = l[:]
# remove a digit
del _temp[len(_temp) - i - 1]
# check if it is divisible by three
if sum(_temp) % 3 == 0:
# if so, this is our solution (the digits are removed in order)
return int("".join(str(n) for n in _temp))
# try every combination of removing a second digit
for j in range(1, len(_temp)):
# copy list of digits again
_temp2 = _temp[:]
# remove another digit
del _temp2[len(_temp2) - j - 1]
# check if this combination is divisible by three
if sum(_temp2) % 3 == 0:
# if so, append it to the list of possibilities
possibilities.append(int("".join(str(n) for n in _temp2)))
# return the largest solution
return max(possibilities)
I tried a lot but test case 3 fails .Sorry for bad variable names
import itertools
def solution(l):
a=[]
k=''
aa=0
b=[]
for i in range(len(l)+1):
for j in itertools.combinations(l,i):
a.append(j)
for i in a:
if sum(i)>=aa and sum(i)%3==0 and len(b)<len(i):
aa=sum(i)
b=i[::-1]
else:
pass
b=sorted(b)[::-1]
for i in b:
k+=str(i)
if list(k)==[]:
return 0
else:
return k

Find the smallest equally divisible in a range of numbers in Python, puzzle

I'm trying to solve a projecteuler puzzle detailed below. My current function works for the numbers 1 to 10, but when I try 1 to 20 it just loops forever without a result.
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
def calculate():
results = dict()
target = 20
num_to_test = 1
while len(results) < target:
for j in range(1, target+1):
results[num_to_test] = True
if num_to_test % j != 0:
# current num_to_test failed in the 1-10, move on
del results[num_to_test]
break
num_to_test += 1
return min(results)
Can anyone see any issues in the logic, and especially I'd like to know why it is working for a target of 10, but not 20. Thanks
Your algorithm is pretty inefficient, but the core of your problem is that your results dictionary is accumulating 1 value for each integer that's evenly divisible by the numbers from 1-20, and your while loop is trying to keep going until it has 20 such numbers.
This is one correct way to implement this inefficient algorithm:
def calculate():
target = 20
candidate = 1
success = False
divisors = range(1, target+1)
while not success:
for divisor in divisors:
if candidate % divisor != 0:
candidate += 1
break
else:
success = True
return candidate
Note that the else clause really is on the for loop, not the if. From the tutorial on flow control:
Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement.
A somewhat more concise expression would be:
candidate = 0
while not success:
candidate += 1
success = all((candidate % divisor == 0 for divisor in divisors))
That uses a generator expression so all can short-circuit and avoid doing unnecessary calculation.
Since this is a puzzle I'll pass on suggesting better algorithms.
actually I have very efficient algorithm for that problem.
I'll not give you the code, but I could show you the way
For N = 10
1.Calculate all factors of all numbers from 5 to 10:
[[2, 3], [7], [2, 2, 2], [3, 3], [2, 5]]
2.calculate maximum number of each prime in the list
{2: 3, 3: 2, 5: 1, 7: 1}
3.get product of key power value
2^3 * 3^2 * 5 * 7 = 2520
A lot of the other answers mention the original code being inefficient, but they still loop through almost every number. Wouldn't it be more efficient to utilize an lcm function?
def calculate(num, current_lcm = 1):
if (num == 1): return current_lcm
return calculate(num - 1, lcm(num, current_lcm))
def lcm(a, b):
return a * b // gcd(a, b)
def gcd(a, b):
while b:
a, b = b, a % b
return a
print calculate(20)
While your algorithm is very inefficient, it may help a little to make this small change
if num_to_test % j = 0:
results[num_to_test] = True
else:
# current num_to_test failed in the 1-10, move on
break
Not sure why you are storing them all though? For debugging perhaps?
Hint. It would be better to calculate the prime factors of the result and simply multiply those together.
# spoiler
def calculate(target):
n = 1
for i in range(1, target+1):
for j in range(1, target+1):
if (n * j) % i == 0:
n *= j
break
return n
Dont store em all, instead just return early when you find it, get rid of that result dictionary, this is not optimal at all by the way, just a clean up
def calculate():
target = 20
num_to_test = 0
while True:
num_to_test += target
if all((num_to_test % j == 0) for j in range(1,target+1)):
return num_to_test
return -1
Also you dont need to test numbers that aren't multiples of your maximum. It'll run 20 times faster.
I switched to using a generator to test to see if the number was divisible by all() of the nubmers from 1 to 20
Props for writing your own algorithm and not copying one :)

Categories

Resources