Implementation of infix # for lists - python

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.

Related

Comparing Two Functions for Recursive Digit Sum

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))

'float' object is not iterable in for loop

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.

Python - TypeError: 'NoneType' object is not iterable Exit Code at CodeWars - Are they the same?

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 ...

Q: list assignment index out of range

>>> def lcm(a,b):
if a<<b:
c=a
a=b
b=c
c=0
lit=[a,b,c]
n=3
while (not lit[n%3]%lit[(n%3)+1]==0):
lit[(n%3)+2]=lit[n%3]%lit[(n%3)+1]
if lit[(n%3)+2]==0:
d=lit[(n%3)+2]
print d
else:
n=n+1
This is the code, trying to build a function lcm that finds the least common multiplier of a and b. Not really the cleanest code of the bunch, but sadly this was all I could do. It would really be nice if this lump of code could be a little lighter.
So, err, back to the point, I called for lcm, and it just blurts out error messages.
This is what it says:
>>> lcm(78696,19332)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
lcm(78696,19332)
File "<pyshell#1>", line 10, in lcm
lit[(n%3)+2]=lit[n%3]%lit[(n%3)+1]
IndexError: list assignment index out of range
Aaaaand I have got absolutely no idea what I am supposed to do now.
What can I do now?
Python lists are zero-indexed.
So lit[0] = a, lit[1] = b, and lit[2] = c.
lit[(n%3)+2]=lit[n%3]%lit[(n%3)+1]
If n = 1, then (n%3)+2 equals 3. If n = 2, then (n%3)+2 equals 4.
If you want to guarantee that you're accessing your list at a valid index, then you want to % by the length of the list- which you're doing, just not at the right place.
Without looking too deeply into your code, I think it's just another lesson that order of operations matters. Try (n+2)%3 instead of (n%3)+2.
x%3 will always be within the range [0, 2]- so that's why you want to mod at the very end. (x%3+n ends up in the range [n, 2+n].)
n%3 can be as big as 2. so n%3 + 1 could be as much as 3. The list lit has only 3 items, so at this line,
lit[(n%3)+2]=lit[n%3]%lit[(n%3)+1]
if n%3 == 2, then accessing lit[(n%3)+1] will lead to index out of range error.

Error in below python code

I am new to python program. the below code has some error with list.
len = []
def collatz_length(n,count):
++count
if len[n]:
return len[n]
if n == 1:
len[n] = count
elif n & 1:
len[n] = count + collatz_length(3 * n + 1,0)
else:
len[n] = count + collatz_length(n >> 1,0)
return len[n]
print collatz_length(13,0)
i am trying to figure out the length.But the gives error
OUTPUT
Traceback (most recent call last):
File "collatz.py", line 21, in <module>
print collatz_length(13,0)
File "collatz.py", line 9, in collatz_length
if len[n]:
IndexError: list index out of range
It means that n is beyond the length of the list (which is initially zero). Rather than doing len[n], you want to see if n is in your list:
# Renaming your array to my_array so that it doesn't shadow the len() function,
# It's also better to put it as a parameter, not a global
def collatz_length(n, count, my_array):
if n < len(my_array):
return my_array[n]
# ... all your elses
If you have an array with 5 things in it, and try to access array[5], you are reading outside the bounds of the array. I think that is what is happening, but your code is also very hard to understand. If that's not what is happening, you may need to add some comments or otherwise clarify what you are doing. It looks like you have an empty array and are trying to access location 13 in it, which makes no sense.

Categories

Resources