Working with Python Arrays - python

What is wrong with this code please:
from array import array
import math
def solution(A):
A = array('i')
for i in A:
if i > 0:
digits = int(math.log10(i))+1
elif i == 0:
digits = 1
else:
digits = int(math.log10(-i))+2
if digits == 2:
sum += i
return sum
The task is to write a function that given an array A consisting of N integers, returns the sum of all two digit numbers

This will do the job
import math
def solution(A):
#A = array('i')
sumofarr=0
for i in A:
if i != 0:
digits = int(math.log10(math.fabs(i)))+1
if digits == 2:
sumofarr += i
return sumofarr
solution([12,3,45]) #output 57
Note that there is no need to separate between positive and negative numbers. Just take the absolute value. Also, you need to initialize the sumofarr variable at the beginning. Also it is better not to use sum as a name for variable, as this is already used as a name of function in python.

the problem with your code is that you don't initialize sum, don't have the correct indentation, overwrite the input argument and the check if a number is of 2 digit is more complicate that it need to be
here is a more simple version
def mysum(A):
total = 0
for i in A:
if 10 <= abs(i) < 100: # abs if you want to include negative numbers
total += i
return total
test
>>> test = [1, 2, 10, 80, 20, -10, -20, 500]
>>> mysum(test)
80
or with the build-in sum and a generator expression
>>> sum( i for i in test if 10 <= abs(i) < 100 )
80
>>>

Related

How do I create a loop that squares an integer until it reaches a certain number of digits?

The task:
Using python, create a function that uses a loop to determine how many
times a number can be squared until it reaches at least a twenty eight
digit number.
Ex: It takes three times to reach a three digit number, starting with
2: 2^2 = 4, 4^2 = 16, 16^2 = 256
Below is what I've tried:
def squaring():
maximum = int(len(28))
for i in range(3, maximum):
print(i**2)
I've also tried:
def squaring():
i = 3
while len(str(i)) < 28:
i = i ** 2
print(i)
Your first example doesn't work, as len is not defined for integers.
Your second example is actually quite right: You can add a counter to check how many times you've multiplied the original number:
def squaring():
counter = 0
i = 3
while len(str(i)) < 28:
i = i ** 2
counter += 1
print(i)
return counter
print(f'The number of squares: {squaring()}')
It's not really necessary to convert anything to a string. It can be done like this:
def count_squares(n):
count = 0
while n < 10**27+1:
n *= n
count += 1
return count
print(count_squares(3))
Output:
6
A Update to the function you created, just passing a parameter to pass number of your choice and adding a iterator 'i' in order to get x-times the number is squared
def squaring(input_number):
number = input_number
i = 0
while len(str(number)) <= 28:
number = number ** 2
i += 1
print(number)
return str(i)+'x'
You can transform the number into a string and you evaluate the len len(str(i**2)) and put a condition
You can Use While True until your Conditions occur!
‍‍
_iter = 0
i = 2
while True:
i = i**2
_iter += 1
if len(str(i)) >=28:
break
print(_iter)

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

Digital Root and Persistence Function

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

Reversing an integer using recursion in Python

While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))

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