Trying to find sum of digits between two numbers - python

Trying to figure out how to find the sum of digits between two numbers(including those numbers) using a function in python.
I tried recursion for each individual argument and then subtracted them to compensate for the numbers in between. Then I added these two and got my sum, which is incorrect for every argument unless the digits are below 10. Not sure of the proper way to approach this problem, please help.
def sum_digits(a, b):
"""sum of digits between two numbers"""
sum = 0
ones = a - b
if ones < 0:
ones = ones * -1
if a >= 10 and b >= 10:
sum += ones
while a > 0 and b > 0:
d = a % 10 + b % 10
a = a // 10
b = b // 10
sum += d
return sum

def sum_digits(a, b):
sum = 0
for i in range(a,b+1):
for e in (str(i)):
sum += int(e)
return sum
print(sum_digits(17, 20))

Does this work ?
this works basically by getting the numbers within a range. Now since endrange is usually one less, I manually add a 1 to the endrange
startNumber = 1
endNumber = 5
total = 0;
for i in range(startNumber,endNumber+1):
print(i)
total += i
print total
Thanks

Just sum the digit sum for every number from the first argument to the last. For more ways to do each digit sum, see Sum the digits of a number - python
def sum_digits(a, b):
total = 0
for number in range(a,b+1):
total += sum(int(digit) for digit in str(number))
return total

Here you go:
def sum_digits(a, b):
sum = 0
for i in range(a, b + 1):
number = i
while (number > 0):
sum += number % 10
number = number // 10
return sum
print(sum_digits(17, 20))

My approach:
def sum_of_products(lst, s, f):
result = 0
for i, item in enumerate(range(s, f+1)):
lst[i] = list(map(int, str(item)))
result += sum(lst[i])
return result
lst = [x for x in range(0, 10)]
x = sum_of_products(lst, 14, 20)
print(x)

My 2 cents would to point out that there should be a closed-form formula that doesn't involve looping trough the whole range.
For example, we know that the sum of n numbers is
n*(n-1)/2
and for the sum of digits 0 to 9 it is 45 == 9*10/2
01
02
03
04
05
06
07
08
09
then it becomes a bit more complicated for the next 10 numbers:
10
11
12
13
14
15
16
17
18
19
the sum is 10 times the tens(decades) plus 45.
and then we could have:
for 00..09 we have 0*10+45
for 10..19 we have 1*10+45
for 20..29 we have 2*10+45
...
for d0..d9 we have d*10+45
I am too lazy to derive the good formula myself, therefore I Googled it. And below is what I have found:
The formula is simple if we know before hand the number of digits. For example, as per https://oeis.org/A007953 , if the number of n is less than 100 then the closed-form formula is:
For n < 100 equal to (floor(n/10) + n mod 10)
For an arbitrarily large number there is a sample code here: https://www.geeksforgeeks.org/count-sum-of-digits-in-numbers-from-1-to-n/
dsum(10**d - 1) = dsum(10**(d-1) - 1) * 10 + 45*10**(d-1)
to compute the digit sum of a range just find the difference
dsum(b) - dsum(a)

Related

How to determine the range to calculate the last digit of the sum of Fibonacci numbers using Pisano Period?

I already solved this problem. If I understood correctly the logic is the following: since we need the last digit of a sum of Fibonacci numbers we can use:
𝐹n mod 10 == (𝐹n % Pisano 10) mod 10
My issue is with the range of the sum. I don't know how to find it. Since Pisano 10 = 60, the last digits repeat with a period of 60 so I don't need to calculate the Fibonacci values from 0 to N but I don't know how to determine this range.
I found solutions for this problem but I never understood how they found their range. For example:
Original here
def sum_fib_last(n):
if(n <= 1):
return n
previous = 0
current = 1
rem = n % 60 #60 is Pisano period of 10
for i in range(2, rem + 3):
previous, current = current, (previous + current) % 60
return(current-1) % 10
I don't know why the range is from (2 to rem+3) and why we return the Fibo value minus 1. Similar solution
This solution uses a different range:
def last_digit(n):
a, b = 0, 1
for i in range((n + 2) % 60):
a, b = b, (a + b) % 10
return 9 if a == 0 else a - 1
I need help to understand how these ranges where determined, I don't understand the logic behind them.
They should have been a little bit clearer. The sum of the first n Fibonacci numbers is Fib(n + 2) - 1. This is easy to prove by induction.

Recursive function in python to find the sum of digits of number

I want to use a recursive algorithm for the function, which should print out the sum of all the digits of a given number.
Here is my code. For example, sum_of_digits(343) will return an output of 10.
numbers = [1, 2]
def sum_of_digits(n):
for n in
sum_of_digits(343)
The output I'm trying to achieve: 10
If you have to use recursion, one method would be to get the individual digits by modding n with 10 and adding that to the sum of the remaining digits (computed by sum_of_digits(n // 10):
def sum_of_digits(n):
if n < 10:
return n
return (n % 10) + sum_of_digits(n // 10)
print(sum_of_digits(343))
Output:
10
def sum_of_digits(n):
result = 0
for x in str(n):
result += int(x)
return result
sum_of_digits(343) # 10
How about this simplest solution:
number = 343
sum_of_digits = sum(map(int, str(number)))
print(sum_of_digits)
10

Find the number of digits after the decimal point [duplicate]

This question already has answers here:
Easy way of finding decimal places
(16 answers)
Closed 4 months ago.
I'm trying to write a Python 2.5.4 code to write a function that takes a floating-point number x as input and returns the number of digits after the decimal point in x.
Here's my code:
def number_of_digits_post_decimal(x):
count = 0
residue = x -int(x)
if residue != 0:
multiplier = 1
while int(multiplier * residue) != (multiplier * residue):
count += 1
multiplier = 10 * multiplier
print count
print multiplier
print multiplier * residue
print int(multiplier * residue)
return count
print number_of_digits_post_decimal(3.14159)
The print statements within the while loop are only for debugging purposes.
Now when I run this code, I get the following as output.
1
10
1.4159
1
2
100
14.159
14
3
1000
141.59
141
4
10000
1415.9
1415
5
100000
14159.0
14158
6
1000000
141590.0
141589
7
10000000
1415900.0
1415899
8
100000000
14159000.0
14158999
9
1000000000
....
The final value of count as returned by this function is 17.
How to modify this code in order to achieve our desired result?
Here's a shortcut that you might like:
def num_after_point(x):
s = str(x)
if not '.' in s:
return 0
return len(s) - s.index('.') - 1
This was interesting! So if you run the following:
x = 3.14159
residue = x - int(x)
print residue
You will get the following result:
0.14158999999999988
This decimal does in fact have 17 digits. The only way that I found to override this was to avoid doing the subtraction (which is the root cause of the error, as you can see from the inaccuracy here). So this code should work as you expect:
def number_of_digits_post_decimal(x):
count = 0
residue = x -int(x)
if residue != 0:
multiplier = 1
while not (x*multiplier).is_integer():
count += 1
multiplier = 10 * multiplier
return count
This will just shift the decimal to the right until python identifies it as an integer (it will do a rightward shift exactly the number of times you want too). Your code actually worked as you intended for it to, something unintended just happened during the subtraction process. Hope this helps!
def decimal_places(f):
exp = -1
remainder = True
while remainder:
exp += 1
a = f * 10**exp
remainder = int(a) - a
return(exp)
def precision(f):
integer, remainder = str(f).split('.')
return len(remainder)

Optimise the solution to Project Euler 12 (Python)

I have the following code for Project Euler Problem 12. However, it takes a very long time to execute. Does anyone have any suggestions for speeding it up?
n = input("Enter number: ")
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
print "Numbers of divisors: ", len(genfact(n))
print
m = input("Enter the number of triangle numbers to check: ")
print
for i in xrange (2, m+2):
a = sum(xrange(i))
b = len(genfact(a))
if b > 500:
print a
For n, I enter an arbitrary number such as 6 just to check whether it indeed returns the length of the list of the number of factors.
For m, I enter entered 80 000 000
It works relatively quickly for small numbers. If I enter b > 50 ; it returns 28 for a, which is correct.
My answer here isn't pretty or elegant, it is still brute force. But, it simplifies the problem space a little and terminates successfully in less than 10 seconds.
Getting factors of n:
Like #usethedeathstar mentioned, it is possible to test for factors only up to n/2. However, we can do better by testing only up to the square root of n:
let n = 36
=> factors(n) : (1x36, 2x18, 3x12, 4x9, 6x6, 9x4, 12x3, 18x2, 36x1)
As you can see, it loops around after 6 (the square root of 36). We also don't need to explicitly return the factors, just find out how many there are... so just count them off with a generator inside of sum():
import math
def get_factors(n):
return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)
Testing the triangular numbers
I have used a generator function to yield the triangular numbers:
def generate_triangles(limit):
l = 1
while l <= limit:
yield sum(range(l + 1))
l += 1
And finally, start testing:
def test_triangles():
triangles = generate_triangles(100000)
for i in triangles:
if get_factors(i) > 499:
return i
Running this with the profiler, it completes in less than 10 seconds:
$ python3 -m cProfile euler12.py
361986 function calls in 8.006 seconds
The BIGGEST time saving here is get_factors(n) testing only up to the square root of n - this makes it heeeaps quicker and you save heaps of memory overhead by not generating a list of factors.
As I said, it still isn't pretty - I am sure there are more elegant solutions. But, it fits the bill of being faster :)
I got my answer to run in 1.8 seconds with Python.
import time
from math import sqrt
def count_divisors(n):
d = {}
count = 1
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
for _,v in d.items():
count = count * (v + 1)
return count
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
start = time.time()
answer = main()
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (answer, elapsed))
Here is the output showing the timedelta and correct answer:
$ python ./project012.py
result 76576500 returned in 1.82238006592 seconds.
Factoring
For counting the divisors, I start by initializing an empty dictionary and a counter. For each factor found, I create key of d[factor] with value of 1 if it does not exist, otherwise, I increment the value d[factor].
For example, if we counted the factors 100, we would see d = {25: 1, 2: 2}
The first while loop, I factor out all 2's, dividing n by 2 each time. Next, I begin factoring at 3, skipping two each time (since we factored all even numbers already), and stopping once I get to the square root of n+1.
We stop at the square_root of n because if there's a pair of factors with one of the numbers bigger than square_root of n, the other of the pair has to be less than 10. If the smaller one doesn't exist, there is no matching larger factor.
https://math.stackexchange.com/questions/1343171/why-only-square-root-approach-to-check-number-is-prime
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
Now that I have gotten each factor, and added it to the dictionary, we have to add the last factor (which is just n).
Counting Divisors
Now that the dictionary is complete, we loop through each of the items, and apply the following formula: d(n)=(a+1)(b+1)(c+1)...
https://www.wikihow.com/Determine-the-Number-of-Divisors-of-an-Integer
All this formula means is taking all of the counts of each factor, adding 1, then multiplying them together. Take 100 for example, which has factors 25, 2, and 2. We would calculate d(n)=(a+1)(b+1) = (1+1)(2+1) = (2)(3) = 6 total divisors
for _,v in d.items():
count = count * (v + 1)
return count
Calculate Triangle Numbers
Now, taking a look at tri_number(), you can see that I opted to calculate the next triangle number in a sequence without manually adding each whole number together (saving me millions of operations). Instead I used T(n) = n (n+1) / 2
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/runsums/triNbProof.html
We are providing a whole number to the function as an argument, so we need to solve for n, which is going to be the whole number to add next. Once we have the next number (n), we simply add that single number to num and return
S=n(n+1)2
S=n2+n2
2S=n2+n
n2+n−2S=0
At this point, we use the quadratic formula for : ax2+bx+c=0.
n=−b±√b2−4ac / 2a
n=−1±√1−4(1)(−2S) / 2
n=−1±√1+8S / 2
https://socratic.org/questions/how-do-you-solve-for-n-in-s-n-n-1-2
So all tri_number() does is evaluate n=1+√1+8S / 2 (we ignore the negative equation here). The answer that is returned is the next triangle number in the sequence.
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
Main Loop
Finally, we can look at main(). We start at whole number 1. We count the divisor of 1. If it is less than 500, we get the next triangle number, then try again and again until we get a number with > 500 divisors.
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
I am sure there are additional ways to optimize but I am not smart enough to understand those ways. If you find any better ways to optimize python, let me know! I originally solved project 12 in Golang, and that run in 25 milliseconds!
$ go run project012.go
76576500
2018/07/12 01:56:31 TIME: main() took 23.581558ms
one of the hints i can give is
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
change that to
def genfact(n):
t=[]
for i in xrange(1,numpy.sqrt(n)+1):
if(n%i==0):
t.append(i)
t.apend(n/i)
since if a is a divisor than so is b=n/a, since a*b=a*n/b=n, That should help a part already (not sure if in your case a square is possible, but if so, add another case to exclude adding the same number twice)
You could devise a recursive thing too, (like if it is something like for 28, you get 1,28,2,14 and at the moment you are at knowing 14, you put in something to actually remember the divisors of 14 (memoize), than check if they are alraedy in the list, and if not, add them to the list, together with 28/d for each of the divisors of 14, and at the end just take out the duplicates
If you think my first answer is still not fast enough, ask for more, and i will check how it would be done to solve it faster with some more tricks (could probably make use of erastothenes sieve or so too, and some other tricks could be thought up as well if you would wish to really blow up the problem to huge proportions, like to check the first one with over 10k divisors or so)
while True:
c=0
n=1
m=1
for i in range(1,n+1):
if n%i==0:
c=c+1
m=m+1
n=m*(m+1)/2
if c>500:
break
print n
this is not my code but it is so optimized.
source: http://code.jasonbhill.com/sage/project-euler-problem-12/
import time
def num_divisors(n):
if n % 2 == 0: n = n / 2
divisors = 1
count = 0
while n % 2 == 0:
count += 1
n = n / 2
divisors = divisors * (count + 1)
p = 3
while n != 1:
count = 0
while n % p == 0:
count += 1
n = n / p
divisors = divisors * (count + 1)
p += 2
return divisors
def find_triangular_index(factor_limit):
n = 1
lnum, rnum = num_divisors(n), num_divisors(n + 1)
while lnum * rnum < 500:
n += 1
lnum, rnum = rnum, num_divisors(n + 1)
return n
start = time.time()
index = find_triangular_index(500)
triangle = (index * (index + 1)) / 2
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (triangle, elapsed))

Digital sum, Python

I need to write a code that counts the sum of the digits of a number, these is the exact text of the problem:The digital sum of a number n is the sum of its digits. Write a recursive function digitalSum(n) that takes a positive integer n and returns its digital sum. For example, digitalSum(2019) should return 12 because 2+0+1+9=12. These is the code I wrote :
def digitalSum(n):
L=[]
if n < 10:
return n
else:
S=str(n)
for i in S:
L.append(int(i))
return sum(L)
These code works fine, but it's not a recursive function, and I'm not allowed to change any int to str. May you help me?
Try this:
def digitalSum(n):
if n < 10 :
return n
return n % 10 + digitalSum( n // 10 )
Edit: The logic behind this algorithm is that for every call of the recursive function, we chop off the number's last digit and add it to the sum. First we obtain the last digit with n % 10 and then we call the function again, passing the number with the last digit truncated: n // 10. We only stop when we reach a one-digit number. After we stop, the sum of the digits is computed in reverse order, as the recursive calls return.
Example for the number 12345 :
5 + digitalSum( 1234 )
5 + 4 + digitalSum( 123 )
5 + 4 + 3 + digitalSum( 12 )
5 + 4 + 3 + 2 + 1 <- done recursing
5 + 4 + 3 + 3
5 + 4 + 6
5 + 10
15
It's homework, so I'm not writing much code. Recursion can be used in the following way:
get the first (or last) digit
format the rest as a shorter number
add the digit and the digital sum of the shorter number (recursion!)
This is more of a question related to algorithms.
Here is your answer:
def digit_sum(a):
if a == 0:
return 0
return a % 10 + digit_sum(a/10)
Let me know if you don't understand why it works and I'll provide an explanation.
Some hints:
You can define inner functions in Python
You can use the modulus operator (look up its syntax and usage) to good effect, here
There's no need to build up an explicit list representation with a proper recursive solution
EDIT The above is a bit "bad" as a general answer, what if someone else has this problem in a non-homework context? Then Stack Overflow fails ...
So, here's how I would implement it, and you need to decide whether or not you should continue reading. :)
def digitalSum(n):
def process(n, sum):
if n < 10:
return sum + n
return process(n / 10, sum + n % 10)
return process(n, 0)
This might be a bit too much, but even in a learning situation having access to one answer can be instructive.
My solution is more a verbose than some, but it's also more friendly towards a tail call optimizing compiler, which I think is a feature.
def digital_sum(number):
if number < 10:
return number
else:
return number % 10 + digital_sum(number / 10)
def sumofdigits(a):
a = str(a)
a = list(a)
b = []
for i in a:
b.append(int(i))
b = sum(b)
if b > 9:
return sumofdigits(b)
else:
return b
print sumofdigits(5487123456789087654)
For people looking non-recursive ways,
Solution 1:
Using formula,
digits = int(input())
res = (digits * (digits + 1) // 2)
Solution 2:
Using basic syntax
numbers = [6, 5, 3, 8, 4, 2, 5, 4, 11]
total = numbers[0]
print(f'{total}')
for val in numbers[1:]:
print(f'{total} + {val} = {total + val}')
total += val
gives
6
6 + 5 = 11
11 + 3 = 14
14 + 8 = 22
22 + 4 = 26
26 + 2 = 28
28 + 5 = 33
33 + 4 = 37
37 + 11 = 48
Still you can do it in O(log10 n)...cancel out all the digits that adds to 9 then if no numbers left,9 is the answer else sum up all the left out digits...
def rec_sum_Reduce(n) :
ans = 0
for i in map(int,str(n)) :
ans = 1+(ans+i-1)%9
return ans
def drs_f(p):
drs = sum([int (q) for q in str(p)])
while drs >= 10:
drs = sum([int(q) for q in str(drs)])
return drs
def digitalSum(n):
if n < 10:
return n
else:
return ???
The 1st part is from your existing code.
The ??? is the part you need to work out. It could take one digit off n and add it to the digitalSum of the remaining digits.
You don't really need the else, but I left it there so the code structure looks the same

Categories