calculating the sum of digits in a list in python - python

I am new to math problems in python but basically i have the following code:
a = list(range(1,10000))
str(a)
sum_of_digits = sum(int(digit) for digit in str(a[9998]))
print(sum_of_digits)
this allows me to calculate the sum of the digits of a given number in the list a. but instead of feeding numbers into this one by one, i want an efficient way to calculate the sum of the digits of all the numbers in a and print them all out at once. I can't seem to figure out a solution but i know the answer is probably simple. any help is appreciated!
edit: i didnt know this post would get this much attention, for those wanting more clarification i basically want to know which digits in the list of range 1,9999 has a sum of 34 or more. i think everyone thought i simply wanted to take the sum of digits of each list element and then compile a total sum. in any case, that method helped me solve the actual problem

A good, straightforward way to do this is to use the modulo % operator, along with floor division \\:
total_sum = 0
for num in a:
sum_of_digits = 0
while (num != 0):
sum_of_digits = sum_of_digits + (num % 10)
num = num//10
total_sum = total_sum + sum_of_digits
print total_sum
Here, the expression n % 10 returns the remainder of dividing n by 10, or in other words, it returns the digit in the units place of that number. What the while loop is doing is repeatedly dividing the number by 10, then adding the number in the units place to the total.
Note that the \\ (floor division) is important here, as it gets rid of any decimal value in the number, which is needed for modulo % to work properly.
Note: This solution is massively more efficient than any algorithm which relies on str().

i want an efficient way to calculate the sum of the digits of all the numbers in a
If you truly want an efficient way, do not calculate the sum of the digit sum of all the individual numbers. Instead, calculate the total digit sum of the entire range1 at once.
For example, in the range up to and including 123, we do not have to write out all the individual numbers to see that the last digit will cycle through the numbers 1-9 a total of 12 times, plus the numbers 1-3 once. The middle digit cycles through 1-9 once, showing each 10 times, and then another 10 times 1 and 4 times 2. And for the first digit, only the 1 appears 24 times. Thus, the total is 45*12 + 1+2+3 + 45*10 + 10 + 8 + 24 = 1038.
You can put this into a recursive formula using "a bit" of modulo magic.
def dsum(n, f=1, p=1):
if n:
d, r = divmod(n, 10)
k = (45*d + sum(range(r)))*f + r*p
return dsum(d, f*10, p + f*r) + k
return 0
This yields the same results as the "naive" approach, but with a running time of O(log n) instead of O(n) it can be used to calculate the digit sum of ridiculously large ranges of numbers.
>>> n = 1234567
>>> sum(int(c) for i in range(1, n+1) for c in str(i))
32556016
>>> dsum(n)
32556016
>>> dsum(12345678901234567890)
1047782339654778234045
1) This is assuming your list is always a range of numbers starting at 1 up to some upper bound, although this would also work for a range not starting at 1 by calculating the digit sum for the upper bound and then subtracting the digit sum for the lower bound. If the list is not a range, then there's no way around calculating the digit sum for all the individual numbers, though.

Try this:
sum(int(i) for j in range(1,10000) for i in str(j))
It is the same, but works slowly:
lst = []
for j in range(10000):
for i in str(j):
lst.append(int(i))
print(sum(lst))

Related

Minimum number from matchsticks, python

I'm having trouble finding the smallest number possible from the following question:
Matchsticks are ideal tools to represent numbers. A common way to represent the ten decimal digits with matchsticks is the following:
This is identical to how numbers are displayed on an ordinary alarm clock. With a given number of matchsticks you can generate a wide range of numbers. We are wondering what the smallest and largest numbers are that can be created by using all your matchsticks.
Input:
On the first line one positive number: the number of testcases, at most 100. After that per testcase:
One line with an integer n (2 <= n <= 100): the number of matchsticks you have.
Output:
Per testcase:
One line with the smallest and largest numbers you can create, separated by a single space. Both numbers should be positive and contain no leading zeroes.
I've tried multiple different ways to try to solve this problem, I'm currently trying to:
find the minimal number of digits needed for the smallest number
send digit to a function minimum() which should generate all the different combinations of numbers that are the length of digits. I want to store all these numbers in a list and then take min() to get the smallest one. I'm not getting this part to work, and would appreciate some inspiration.
Something to remember is that the number can't start with a 0.
if 2 <= n <= 100:
value = (n+6)//7
Unless I'm mistaken, this should work for part 2 (added a fix for 17, 24...):
numdict = {2:1,3:7,4:4,5:2,6:0,7:8,8:10,9:18,10:22,11:20,12:28,13:68}
def min_stick(n):
if 2 <= n <= 13:
return numdict[n]
digits = (n + 6) // 7
base = str(numdict[7+n%7])
if base == '22':
base = '200'
return int(base+"8"*(digits - len(base)))
And, though this one's a no-brainer:
def max_stick(n):
if n%2:
return int("7"+"1"*((n-3)//2))
return int("1"*(n//2))
Ok, so just for the sake of it, I coded what you asked: a recursive function that returns all possible combinations with n matchsticks.
stick = {0:6,1:2,2:5,3:5,4:4,5:5,6:6,7:3,8:7,9:6}
def decompose(n):
retlist = []
if n==0:
return [""]
for i in stick:
if (left := n-stick[i]) >1 or left == 0:
retlist += [str(i)+el for el in decompose(left)]
return retlist
def extr_stick(n):
purged_list = [int(i) for i in decompose(n) if not i.startswith('0')]
return min(purged_list), max(purged_list)
It becomes slow when n grows, but anyway...
extr_stick2(30)
Out[18]: (18888, 111111111111111)

I need help finding a smart solution to shorten the time this code runs

2 days ago i started practicing python 2.7 on Codewars.com and i came across a really interesting problem, the only thing is i think it's a bit too much for my level of python knowledge. I actually did solve it in the end but the site doesn't accept my solution because it takes too much time to complete when you call it with large numbers, so here is the code:
from itertools import permutations
def next_bigger(n):
digz =list(str(n))
nums =permutations(digz, len(digz))
nums2 = []
for i in nums:
z =''
for b in range(0,len(i)):
z += i[b]
nums2.append(int(z))
nums2 = list(set(nums2))
nums2.sort()
try:
return nums2[nums2.index(n)+1]
except:
return -1
"You have to create a function that takes a positive integer number and returns the next bigger number formed by the same digits" - These were the original instructions
Also, at one point i decided to forgo the whole permutations idea, and in the middle of this second attempt i realized that there's no way it would work:
def next_bigger(n):
for i in range (1,11):
c1 = n % (10**i) / (10**(i-1))
c2 = n % (10**(i+1)) / (10**i)
if c1 > c2:
return ((n /(10**(i+1)))*10**(i+1)) + c1 *(10**i) + c2*(10**(i-1)) + n % (10**(max((i-1),0)))
break
if anybody has any ideas, i'm all-ears and if you hate my code, please do tell, because i really want to get better at this.
stolen from http://www.geeksforgeeks.org/find-next-greater-number-set-digits/
Following are few observations about the next greater number.
1) If all digits sorted in descending order, then output is always “Not Possible”. For example, 4321.
2) If all digits are sorted in ascending
order, then we need to swap last two digits. For example, 1234.
3) For
other cases, we need to process the number from rightmost side (why?
because we need to find the smallest of all greater numbers)
You can now try developing an algorithm yourself.
Following is the algorithm for finding the next greater number.
I)
Traverse the given number from rightmost digit, keep traversing till
you find a digit which is smaller than the previously traversed digit.
For example, if the input number is “534976”, we stop at 4 because 4
is smaller than next digit 9. If we do not find such a digit, then
output is “Not Possible”.
II) Now search the right side of above found digit ‘d’ for the
smallest digit greater than ‘d’. For “534976″, the right side of 4
contains “976”. The smallest digit greater than 4 is 6.
III) Swap the above found two digits, we get 536974 in above example.
IV) Now sort all digits from position next to ‘d’ to the end of
number. The number that we get after sorting is the output. For above
example, we sort digits in bold 536974. We get “536479” which is the
next greater number for input 534976.
"formed by the same digits" - there's a clue that you have to break the number into digits: n = list(str(n))
"next bigger". The fact that they want the very next item means that you want to make the least change. Focus on changing the 1s digit. If that doesn't work, try the 10's digit, then the 100's, etc. The smallest change you can make is to exchange two furthest digits to the right that will increase the value of the integer. I.e. exchange the two right-most digits in which the more right-most is bigger.
def next_bigger(n):
n = list(str(n))
for i in range(len(n)-1, -1, -1):
for j in range(i-1, -1, -1):
if n[i] > n[j]:
n[i], n[j] = n[j], n[i]
return int("".join(n))
print next_bigger(123)
Oops. This fails for next_bigger(1675). I'll leave the buggy code here for a while, for whatever it is worth.
How about this? See in-line comments for explanations. Note that the way this is set up, you don't end up with any significant memory use (we're not storing any lists).
from itertools import permutations
#!/usr/bin/python3
def next_bigger(n):
# set next_bigger to an arbitrarily large value to start: see the for-loop
next_bigger = float('inf')
# this returns a generator for all the integers that are permutations of n
# we want a generator because when the potential number of permutations is
# large, we don't want to store all of them in memory.
perms = map(lambda x: int(''.join(x)), permutations(str(n)))
for p in perms:
if (p > n) and (p <= next_bigger):
# we can find the next-largest permutation by going through all the
# permutations, selecting the ones that are larger than n, and then
# selecting the smallest from them.
next_bigger = p
return next_bigger
Note that this is still a brute-force algorithm, even if implemented for speed. Here is an example result:
time python3 next_bigger.py 3838998888
3839888889
real 0m2.475s
user 0m2.476s
sys 0m0.000s
If your code needs to be faster yet, then you'll need a smarter, non-brute-force algorithm.
You don't need to look at all the permutations. Take a look at the two permutations of the last two digits. If you have an integer greater than your integer, that's it. If not, take a look at the permutations of the last three digits, etc.
from itertools import permutations
def next_bigger(number):
check = 2
found = False
digits = list(str(number))
if sorted(digits, reverse=True) == digits:
raise ValueError("No larger number")
while not found:
options = permutations(digits[-1*check:], check)
candidates = list()
for option in options:
new = digits.copy()[:-1*check]
new.extend(option)
candidate = int(''.join(new))
if candidate > number:
candidates.append(candidate)
if candidates:
result = sorted(candidates)[0]
found = True
return result
check += 1

Number of multiples less than the max number

For the following problem on SingPath:
Given an input of a list of numbers and a high number,
return the number of multiples of each of
those numbers that are less than the maximum number.
For this case the list will contain a maximum of 3 numbers
that are all relatively prime to each
other.
Here is my code:
def countMultiples(l, max_num):
counting_list = []
for i in l:
for j in range(1, max_num):
if (i * j < max_num) and (i * j) not in counting_list:
counting_list.append(i * j)
return len(counting_list)
Although my algorithm works okay, it gets stuck when the maximum number is way too big
>>> countMultiples([3],30)
9 #WORKS GOOD
>>> countMultiples([3,5],100)
46 #WORKS GOOD
>>> countMultiples([13,25],100250)
Line 5: TimeLimitError: Program exceeded run time limit.
How to optimize this code?
3 and 5 have some same multiples, like 15.
You should remove those multiples, and you will get the right answer
Also you should check the inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers
EDIT:
The problem can be solved in constant time. As previously linked, the solution is in the inclusion - exclusion principle.
Let say you want to get the number of multiples of 3 less than 100, you can do this by dividing floor(100/3), the same applies for 5, floor(100/5).
Now to get the multiplies of 3 and 5 that are less than 100, you would have to add them, and subtract the ones that are multiples of both. In this case, subtracting multiplies of 15.
So the answer for multiples of 3 and 5, that are less than 100 is floor(100/3) + floor(100/5) - floor(100/15).
If you have more than 2 numbers, it gets a bit more complicated, but the same approach applies, for more check https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers
EDIT2:
Also the loop variant can be speed up.
Your current algorithm appends multiple in a list, which is very slow.
You should switch the inner and outer for loop. By doing that you would check if any of the divisors divide the number, and you get the the divisor.
So just adding a boolean variable which tells you if any of your divisors divide the number, and counting the times the variable is true.
So it would like this:
def countMultiples(l, max_num):
nums = 0
for j in range(1, max_num):
isMultiple = False
for i in l:
if (j % i == 0):
isMultiple = True
if (isMultiple == True):
nums += 1
return nums
print countMultiples([13,25],100250)
If the length of the list is all you need, you'd be better off with a tally instead of creating another list.
def countMultiples(l, max_num):
count = 0
counting_list = []
for i in l:
for j in range(1, max_num):
if (i * j < max_num) and (i * j) not in counting_list:
count += 1
return count

Writing a Python program that finds the square of a number without using multiplication or exponents?

thank you for reading and hopefully responding to my question. I'm stuck trying to write this Python program that finds a number's square without using multiplication or exponents. Instead, I have to get the summation of the first odd n numbers starting from 1. This is what I have so far:
def square():
print("This program calculates the square of a given number")
print("WITHOUT using multiplication! ")
odd = 1
n = eval(input("Enter a number: "))
for odd in range(0, n + 1, 2):
odd = odd + 2
final_square = n + odd
print(n, "squared is", final_square, ".")
EDIT: Hi guys, I can't do 4 + 4 + 4 + 4. I have to do 1 + 3 + 5 + 7, and I'm not sure how. It gives me 4 squared is 11 or something.
Just some tips:
Try not to use eval(), it will evaluate any input given and so it can do something you don't want to do. Instead, use int().
Remember that, say 4*4, is just 4 + 4 + 4 + 4. You're on the right track with a for-loop, but now make the loop iterate n times adding n to itself.
new = 0
for _ in range(n):
new += n
Note that this won't work with negative numbers. If you're going to be dealing with those, perhaps get the absolute value of n at the beginning:
def square(n):
n = abs(n)
....
Since you have been told you have to get the answer by producing the first n odd numbers, then you need to think about how to do that - certainly your loop isn't doing that :
several issues :
you do odd =1, and then use odd in your for loop, the two can't co-exist, so the initial value of odd = 1 is overwritten.
Your loop doesn't produce the first n odd numbers that I can see.
My suggest would be to rework your loop : the first 'n' odd numbers are in the form :
1, 3, 5, ... n*2-1
(Counting from 1 not from zero)
so a loop like this :
final = 0
for c in range(1, n+1): #start counting from 1 to do 1 to n+1
odd = c*2 -1 #Use the series above to generate each odd number.
final += odd
should work
a much more 'pythonic' way to do this is :
final = sum(c*2-1 for c in range(1,n))
This uses a generator to create all of the odd numbers (the equivalent of the loop), and sum the values as they get created.
Go back to the original definition of multiplication.
Just add the number n to itself n times. What's so hard? It's inefficient has hell, but it'll work.
I'm sure there's a more Pythonic way:
def square(n):
sum = 0
for i in range(0,n):
sum = sum + n
return sum

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