Digital Root and Persistence Function - python

Currently I am trying to make a function that returns the digital root and persistence of an integer, for example: digitalRootAndPersistence(9879) returns [6, 2]. Only built in function I can use is sum, and can use another function I made before called toDigitList which must be implemented into the digitalRoot function.
toDigitList function:
def toDigitList(n):
while n < 10:
return [n]
else:
return toDigitList(n // 10) + [n % 10]
My digitalRoot function: (I do not know what I am doing wrong, Im getting no errors, but also no output.)
def digitalRootAndPersistence(n):
x = (n)
count = 0
while n > 1:
x = sum(toDigitList(n))
count += 1
return (x), count
print(digitalRootAndPersistence(9879))

You have a couple of syntactic confusions. The parentheses in these lines of
code are not doing anything.
x = (n)
return (x), count
As noted in comments, n needs to decrease. Specifically, n should become the sum
of the digits. Which means no need for x. Also, the break point is 9, not 1.
def digitalRootAndPersistence(n):
count = 0
while n > 9:
n = sum(toDigitList(n))
count += 1
return n, count

Related

Subset sum with minimum elements

Given a sorted list of integers, always containing 1. Find a target value using the minimum amount of elements to sum to the target value. All numbers can be used more than one.
e.x. {1,9,10} Target = 18, solution is 2 elements (9 twice).
{1,3,5,7} Target = 15, solution is 3 elements (7,7,1 or 5,5,5)
I understand that we should check whether we use an element up to its maximum amount to fill the target value but I am confused on how to correctly count the number of elements used once we have a correct recursive return.
def main():
sections = list(map(int,input().split(" ")))
t = int(input())
print((subset_sum(sections,len(sections)-1,t)), "elements minimum")
def subset_sum(X, i, t):
count = 0
if t == 0:
return 1
if t < 0 or abs(i) == len(X):
return 0
for z in range(0,t//X[i]):
count += subset_sum(X,i-1,t-(z*X[i]))
return count
if __name__ == "__main__":
main()
Is my base case incorrect? Since I want the minimum should the incorrect case return 1? Or do I have a mistake when I call the recursion?
I think the code is trying to solve a different problem than the one described in the title. You seem to be counting the number of different ways to make change for amount t using denominations in X. Here is a version of your code that does this:
def subset_sum(X, i, t):
count = 0
if t == 0:
return 1
if t < 0 or i < 0:
return 0
for z in range(0,t//X[i] + 1):
count += subset_sum(X,i-1,t-(z*X[i]))
return count
subset_sum([5, 2, 1], 2, 30) # 58 ways to make change
# same as the following Mathematica code:
# Length#IntegerPartitions[30, All, {1, 2, 5}]
In order to find the minimum number of coins needed to achieve amount t, you need to modify your inductive step. Instead of adding the amounts for smaller values of t, you need to take the minimum:
from functools import lru_cache
def coin_change(denominations, target):
'Return minimum number of coins with given denominations to make a target sum'
#lru_cache(None)
def f(target):
if target == 0:
return 0
elif target < 0:
return float("inf")
return min(f(target - d) for d in denominations) + 1
return f(target)
coin_change([1, 2, 5], 30) # minimum number of coins is 6

How do I iterate a nonetype variable?

I'm trying to edit my find_winners function where I want to print out values from number_digit and store it into mini. And from there i would use these values to see if it is divisible by f. However it keep saying that mini is a nonetype variable. I know that mini is a function but if a function has value placed in, wouldnt mini be a int function because it has been processed by the previous function? (number_digit) How do i make it such that mini is a iterable function such that the values in mini can be used for subsequent functions?
def number_contains(n,m): # m is the must have digit
while n > 0 and m > 0 and 10 > m:
if n % 10 == m:
break
n = n /10
return (n > 0)
def number_digit(n,d): #n is the list of numbers and d is the wanted number
for i in range(0, n+1):
if number_contains(i,d):
print(i)
return
def find_winners(f,m,n): #f is the factor out number
count = 0
mini = number_digit(n,m)
for i in mini:
if i % f ==0:
count += 1
return count
print(count)

Finding the the largest number in a list that its modulo with a given number is 0

I need to define a recursive function that receives a list of
non-negative integers numbers, and a positive integer m, and returns the largest number from the list that divides by m with no remainder.
I can't use loops or python's max function on a list.
I tried:
def find_max_mod(numbers, m):
mx = 1
mxn = -1
if len(numbers) == 1 and numbers[0] % m == 0:
if mx > numbers[0]:
mx = numbers[0]
return mx
if len(numbers) == 1 and numbers[0] % m != 0:
return -1
elif len(numbers) == 0:
return -1
elif numbers[-1] % m == 0 and numbers[-1] > mx:
mx = numbers[-1]
numbers = find_max_modulo(numbers[:-1], m)
return mx
I can't figure how to save my largest number. Every recursive cycle it over-write on my mx number.
I think I have a problem with the base condition but it is the smallest problem.
You're close, you just need to modify the return statements
elif numbers[-1] % m == 0 and numbers[-1] > mx:
mx = numbers[-1]
numbers = find_max_modulo(numbers[:-1], m)
return mx
to:
elif numbers[-1] % m == 0 and numbers[-1] > mx:
return numbers[-1]
return find_max_modulo(numbers[:-1], m)
This works:
def find_max_mod(list_numbers, large_number, current_max_valid=0):
if list_numbers[0] % large_number == 0:
if current_max_valid < list_numbers[0]:
current_max_valid = list_numbers[0]
if len(list_numbers) > 1:
return find_max_mod(list_numbers[1:], large_number, current_max_valid)
return current_max_valid
list_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
print(find_max_mod(list_numbers, 5))
If you want to work on recursion, you should try to find exercises that fits your theme. For instance, Fibonnacci function for recursion is a good start.
Now as for your question, usually, for a recursive function, you need an if-statement that will stop your program from iterating. That condition may be a variable that will need to be passed thoughout the process as a parameter, or it might be a hard-coded condition to-be-met.
As you need to go through all the list, you need to think about a stop condition in the end of your list. You have multiple choices but I suggest you pop an item at each iteration : item that will be checked if it respects your requirements.
Now, you want to keep the largest number ?
You simply need to check if the item you received from further computations is a better fit than the one you have in your current recursive session : so that you can keep the one that best fits your needs.
Good luck. :)

a recursive function to calculate sum of a number digits

i have to write a recursive function which calculates sum of a number digits,here's the code i tried :
def sum_digit(n):
sum=0
a = n % 10
n //= 10
sum += a
while n > 0 :
sum = sum + sum_digit(n)
return sum
print(sum_digit(67154))
i don't know why i don't get the 23 as answer...my program doesn't come to an end
for example 23 number(please correct me if I'm wrong,I'm a newbie in python),the 3 goes to sum, and n become2,since its > 0 then it should go to while,so now it should calculate sum digit(2),the a become 2 and 2 goes to sum and n become 0 and sum digit(2) returns 2,then it sum with the 3 and i must get 5.
i appreciate your help.
You have an infinite loop because n never changes within the loop. Note that assigning a new value to n in the scope of the called function will not change n in the outer scope.
Also, it seems you are mixing an iterative solution with a recursive one. If you do the recursive call, you do not need the loop, and vice versa.
You can either do it recursively:
def sum_digit(n):
if n > 0:
return sum_digit(n // 10) + n % 10
else:
return 0
Or in an iterative way:
def sum_digit(n):
s = 0
while n > 0:
s += n % 10
n //= 10
return s
Or just using bultin functions (probably not what your teacher wants to see):
def sum_digit(n):
return sum(map(int, str(n)))
i must change the while with a if, and it works,thanks for your comments and sorry for posting such a question here.
This will do the trick:
def sum_digit(n, current_sum=0):
if n == 0:
return current_sum
else:
digit = n % 10
current_sum += digit
n //= 10
return sum_digit(n, current_sum)
The output:
print(sum_digit(67154))
> 23
You were mixing up an iterative method (the while loop) and the recursive method (the function call).
In a recursive function, must make sure you get these things right:
The end condition (in our case, we return the sum when the digit is 0)
and
The recursive call (in our case, going down one digit each time)
Change your code as following:
def sum_digit(n):
sum=0
a = n % 10
n //= 10
sum += a
if n > 0 :
sum = sum + sum_digit(n)
return sum
The reason is n is assigned new reference inside function, but it's invisible outside. so while part is loop died. In fact, while part is executed at most once, so code was changed as above.

Amicable Numbers

I am struggling with optimizing these functions that I have used to calculate the sum of the amicable pairs under 10000. An amicable pair is a pair (a, b) where the sum of the divisors of "a" excluding "a" itself equals b and the sum of the divisors of "b" excluding "b" itself equals "a".
I.e. divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110: The sum of which is 284. And the sum of the divisors of 284 (1, 2, 4, 71 and 142) equals 220.
My code is:
import math
def Divisorsbaritself(x):
divList = [1]
y = 2
while y <= math.sqrt(x):
if x % y == 0:
divList.append(y)
divList.append(int(x / y))
y += 1
return sum(divList)
def amicable():
solution = []
for i in range(10000):
if Divisorsbaritself(Divisorsbaritself(i)) == i:
solution.append(i)
return sum(solution)
print amicable()
I need help with understanding why the amicable function is not working. To me it makes logical sense that the if Divisorsbaritself(Divisorsbaritself(i)) == i: condition is the right condition to include i in the list, but it is giving me 40285, rather than 31626, the answer.
If Divisorsbaritself(i)==i you shouldn't count i.
def amicable():
solution = []
for i in range(10000):
if Divisorsbaritself(i)!=i and Divisorsbaritself(Divisorsbaritself(i)) == i:
solution.append(i)
return sum(solution)
But you should also fix the bug that would be an issue if i is a perfect square and in an amicable pair.
You can improve this with list comprehensions.
def amicable():
solution = [i for i in xrange(10000) if Divisorsbaritself(i)!=i and Divisorsbaritself(Divisorsbaritself(i)) == i]
return sum(solution)
They're amicable numbers only if they're different. So if divsum(i) is equal to i, then that's not included, despite the fact that means that divsum(divsum(i)) also equals i.
In addition, your current check counts the square root of a perfect square twice, even though it's only one factor.
And, on top of that, I wouldn't be using a list then summing it at the end when you can simply use an accumulator. And it's usually faster to do multiplication than square roots so you can change the while loop to take that into account.
Finally, for the love of whatever deities you believe in, comment your code! It'll make it so much easier to understand what's going on, both for others and for yourself six months down the track.
Incorporating those changes gives you the following DivisorsBarItself function:
def DivisorsBarItself(num):
# Maintain sum of factors.
divSum = 1
# Go through every integer up to but excluding sqrt(num).
testnum = 2
while testnum * testnum < num:
# If factor, add it and the complement (guaranteed integer).
if num % testnum == 0:
divSum += testnum + num/testnum
testnum += 1
# If perfect square, add the square root once.
if testnum * testnum == num:
divSum += testnum
# Return the sum.
return divSum
Fixing the logic for detecting amicable numbers and using a sum rather than a list gives you:
def AmicableSum():
# Set sum to zero and process all numbers below 10,000.
solution = 0
for num in range(10000):
# Get the "friend", add only if different and f(f(x)) = x.
numFriend = DivisorsBarItself(num)
if numFriend != num and DivisorsBarItself(numFriend) == num:
solution += num
return solution
print AmicableSum()
which gives the correct result of 31626.
I have fixed the bug now by going:
def Divisorsbaritself(x):
divList = [1]
y = 2
while y <= math.sqrt(x):
if x % y == 0:
if y is not int(x/y):
divList.append(y)
divList.append(int(x / y))
else:
divList.append(y)
y += 1
return sum(divList)
I have written the whole thing you said as a function
def devisor(a):
listOfFactors=[]
for possibleFactor in range(1,a):
if a%x==0:
listOfFactors.append(possibleFactor)
sumOfFactors=0
for item in z:
sumOfFactors+=item
factorsOfNewSumAddedUp=0
for x in range(1,sumOfFactors):
if temp%x==0:
factorsOfNewSumAddedUp+=x
if a==factorsOfNewSumAddedUp:
print("this is a divisor")

Categories

Resources