I'm stumped as to why my solution for the Recursive Digit Sum question on HackerRank is being rejected.
Background
The question:
For an input of string n and integer k, the number h is created by concatenating n "k" times. Find the "super digit" of h by recursively summing the integers until one is left.
For example:
n = '9875', k = 2, so h = 98759875
sum(98759875)= 58
sum(58)= 13
sum(13) = 4
Submissions
My Solution
def superDigit(n, k):
h=n*k
while len(h)>1:
h=str(sum([int(i) for i in h]))
return int(h)
Solution I've Found
def superDigit(n, k):
return 1 + (k * sum(int(x) for x in n) - 1) % 9
My Inquiry to the Community
What am I missing in my solution? Yes it's not as simple as the supplied solution involving the digital root function (which I don't fully understand, I just found it online) but I don't see how my function is supplying incorrect answers. It passes most of the test cases but is rejecting for 1/3 of them.
Here is the result of my research on your case:
You don't supply the typing, so I had to case check to find out you use one str and one int. How do I know this?
Well if you used 2 strs the multiplication would fail:
>>> "10"*"2"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
And if you used 2 ints, h would also be an int, and your sum would fail:
>>> str(sum([int(i) for i in 100]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
So as a result you must have one int and one str. But that also doesn't work since the int*str multiplication uses concatenation instead of the "mathematical" addition:
>>> 10 * "2"
'2222222222'
My solution suggestion is simply to:
Use typing for clarity
Use ints for the multiplication and strs for splitting the digits
This can be done simply by editing only the first two lines:
def superDigit(n: int, k:int) -> int:
h=str(n*k)
while len(h)>1:
h=str(sum([int(i) for i in h]))
return int(h)
Let me know if this helps.
Thanks to some helpful comments from #Tim Roberts, #Paul Hankin, and #yagod I was able to solve the issue. It was in fact due to time-out! All I had to do was update one line: h=str(sum([int(i) for i in n])*(k%9))
Related
I did research solution of this problem for hours but ı can't find any solution. What is the problem in my code?
import numpy as np
q_max = 5
for q in range(1, q_max):
for p in range(0, q_max):
if q>p:
#I want to delete duplicates numbers
a = list(set(p/q))
print(a)
Error:
Traceback (most recent call last):
File "C:\Users\MONSTER\Desktop\gcd.py", line 16, in <module>
alfa = list(set(p/q))
TypeError: 'float' object is not iterable
If you want unique divisors you have to create your set before you start looping, and then add your values to the set. When you're finished looping, you can print the whole set.
The set will deduplicate values, ignoring .add() calls when items already exist in the set (as opposed to the list's .append() method).
q_max = 5
values = set()
for q in range(1, q_max):
for p in range(0, q_max):
if q>p:
values.add(p/q)
print(values)
Your problem is here:
a = list(set(p/q))
set() will cast an iterable (and only an iterable) into a set object - effectively eliminating duplicates. However, you pass it the result of p / q, which is an int divided by an int - a float. The error states you can't pass a float to a function that expects an iterable.
It's unclear why you want to use set() or even list() here. If your expectation is to divide p by q, just do that. a will be a float you can print.
When I am trying to find factorial using below code, it is working for all numbers except '0'. When I give the input as 0, below error is displayed. Can some one help me to understand and fix the error
from functools import reduce
n = int(input())
fact = lambda a, b: a*b if (n>=1) else 1
reduce(fact, range(1,n+1))
Expected result: When input is given as '0' 1 should be displayed as output
Actual result: Below error is displayed
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-124-52f472210976> in <module>
3
4 fact = lambda a, b: a*b if (n>=1) else 1
----> 5 reduce(fact, range(1,n+1))
6
TypeError: reduce() of empty sequence with no initial value
In Python 3, at least, reduce() has an "initializer" parameter, which "is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty" (documentation). So use an initializer of 1. You can also simplify your code by using the multiplication operator in the operator module.
from functools import reduce
from operator import mul
result = reduce(mul, range(1,n+1), 1)
You should understand your error now. The error message says that you tried to use reduce() on an empty sequence with no initial value. Putting in the initial value of 1 solves that.
So I'm doing a challenge from CodeWars that says:
"Given two arrays a and b write a function comp(a, b) that checks whether the two arrays have the "same" elements, with the same multiplicities. "Same" means, here, that the elements in b are the elements in a squared, regardless of the order."
My code for it is:
def comp(array1, array2):
if array1==None or array2==None:
return False
array1 = list(array1)
array2 = list(array2)
array1.sort()
array2.sort()
z= 0
for i in range(len(array1)):
if array1[i]**2 == array2[i]:
z+=1
if z == len(array1):
return True
else:
return False
Now, I know there must be much easier code for this task, but I'm still a beginner programmer.
So all the tests are passed positively.
But I keep getting an exit code:
Traceback (most recent call last):
File "main.py", line 21, in <module>
test.assert_equals(comp(a1, a2), False)
File "/home/codewarrior/solution.py", line 10, in comp
if array1[i]**2 == array2[i]:
IndexError: list index out of range
If I remove the first "if array1= None.... return False" statement, it gives this exit code instead:
Traceback (most recent call last):
File "main.py", line 18, in <module>
test.assert_equals(comp(a1, a2), False)
File "/home/codewarrior/solution.py", line 3, in comp
array2 = list(array2)
TypeError: 'NoneType' object is not iterable
So no matter what, my code has something wrong in it, haha. Any solution to this?
The error you can cam be dueto different lenghts of lists -you do not guard against that.
comp([1,2,3], [1,2])
You can simplify your code using enumerate() on one array and then look into the other one. I highly doubt your arrays need to be cast into a list - they probably already are - and even if, you could do that in one step using sorted():
def comp(array1, array2):
if array1 is None or array2 is None: # compare to None with is
return False
if len(array1) != len(array2):
return False
array1 = sorted(array1)
array2 = sorted(array2)
for idx,num in enumerate(array1):
if num*num != array2[idx]:
return False # early return on first mismatch
return True
You still might get better results if you optimize more - but you can do that on your own time :o) - f.e. think about a check for this:
comp( [2]*100000000,[4]*100000000)
You can easily speed that up if you use a sorted list of a set() of your inputs instead of sorted list and that way you can eliminate about 99999999 checks which will make a dent into your runtime (unless your dataset only contains unique values to begin with). And if you got set()'s .. they are really fast in looking up if something is in them - far better and faster then sorting huge lists to begin with ...
PEP 465 adds the # infix operator for matrix multiplication. The lists however don't implement this as of now. Thus as directed by the documentation I tried to implement my own version of __matmul__.
This is my first attempt.
class Matrices(list):
def __matmul__(self,matrix):
tempmat = [[0 for row in range(len(self))] for col in range(len(matrix))]
for i in range(len(self)):
for j in range(len(matrix[0])):
for k in range(len(matrix)):
tempmat[i][j] += self[i][k] * matrix[k][j]
return tempmat
a = Matrices()
a.append([[1,2],[3,4]])
b = Matrices()
b.append([[5,6],[7,8]])
print(a#b)
However I am getting an error,
Traceback (most recent call last):
File "test.py", line 14, in <module>
print(a#b)
File "test.py", line 7, in __matmul__
tempmat[i][j] += self[i][k] * matrix[k][j]
TypeError: can't multiply sequence by non-int of type 'list'
How do I solve this problem? That is, how do I implement the # character for lists in python?
Updated for rewritten question: Clearly, either self[i][k] or matrix[k][j] is a list, not an int. Looks like you were appending in the code outside when you should have been extending.
Original answer to first problem:
You used [[0 for row in range(self)] for col in range(matrix)], when you probably meant to wrap both self and matrix in len calls. Unless for some crazy reason you implemented __index__ on your Matrices class, it's not a integer, so you can't range over it.
I just started with Python. Had Haskell before. In Haskell, I worked most of the time with/on lists. In Python I want do so.
I have a list of:
l = [1,2,3,4]
How can I add the 4 elements in the list, so that I get 10 as result (1+2+3+4)
I need a recursive function and an iterative (not clean and stable as iterative , but nevertheless).
In Haskell I did this:
sum [] = 0
sumlist(x:xs) = x + sumlist xs
In Python I tried this:
def sumlist(l)
if l == 0: #or Nil, i do not know
result 0
else:
l [0] + sumlist(l)
but that does not work, maybe I am still to focused on Haskell's implementation style.
Would be great if I get some help.
Edit:
If you do not wish to use sum, you can make your own function1:
>>> def sumlist(seq, start=0):
... return sumlist(seq[1:], start + seq[0]) if seq else start
...
>>> lst = [1, 2, 3, 4]
>>> sumlist(lst)
10
>>> lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> sumlist(lst)
45
>>> sumlist(lst, 10) # You can specify a number to start at too
55
>>>
1Note: It is assumed that you will pass in a sequence of numbers.
Just use the sum built-in:
>>> l = [1, 2, 3, 4]
>>> sum(l)
10
>>>
From the docs:
sum(iterable[, start])
Sums start and the items of an iterable from left to right and returns the total. start defaults to 0. The iterable's items are
normally numbers, and the start value is not allowed to be a string.
I haven't used Haskell, but in Python objects are rich in that they know how to work with other objects. You can think of it like the "interface between objects" is well understood, and everyone is expected to behave nicely:
EAFP
Easier to ask for forgiveness than permission. This common Python
coding style assumes the existence of valid keys or attributes and
catches exceptions if the assumption proves false. This clean and fast
style is characterized by the presence of many try and except
statements. The technique contrasts with the LBYL style common to many
other languages such as C.
So the idea is if there a function in the standard library called sum, you can be sure it does at least two things:
Knows how to sum up things it can sum up.
If it doesn't know how to sum it up, it will raise an Exception.
Once you understand how this works, you can start passing anything to sum to see what it does:
>>> sum((1,2,3)) # a list
6
>>> sum([1,2,3]) # a tuple
6
>>> sum((1,)) # a tuple with one object
1
>>> sum([2]) # a list with one object
2
So as long as the item is iterable, sum can do its thing. Of course, when you pass it something it cannot work with, you get the appropriate exception:
>>> sum(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> sum('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Note that a string is iterable in Python, which is why you get a different exception.
After you comment here:
Is there another way summing them up , or is it just this one ?
Its worth pointing out the zen of python which is kind of a guide on what makes code "pythonic", which states:
There should be one-- and preferably only one --obvious way to do it.
So the obvious way to sum things up would be with a function named sum.
Your code isn't actually too far off. empty lists are "falsy", so you can do something like:
def sumlist(lst):
if not lst:
return 0
else:
# Add the first element to the sum of the remaining elements.
return lst[0] + sumlist(lst[1:])
Of course, I'm assuming that you're doing this as part of a homework assignment where you're learning about recursion -- This would be horrible in any sort of production code where you should really just use sum (the builtin function).
If you are looking for a method other than the obvious sum you can use reduce:
>>> l = [1,2,3,4]
>>> import operator
>>> reduce(operator.add, l)
10
If you want another function, you could do:
def sum_l(l):
rtr=0
while l:
rtr+=l.pop()
return rtr
That function is destructive to the list. If you want to keep the list, call it with a copy of the list:
n=sum_l(l[:])
Yet another (that does not destroy the list) is to use a for loop on the iterable:
def sum_l(l):
rtr=0
for e in l:
rtr+=e
return rtr
Here are two ways you can compute the sum:
Just use the in-built sum function:
sum(l)
Using a for loop:
sum_val = 0
for i in range(0, len(l)):
sum_val += l[i]
Using recursion to compute a sum is just waste of computing resources. Do not use recursion until its absolutely necessary.