Summation riddle duplicate values seen - python-3.x

a list the output we get repeated values (3,20,7)
how to remove the repeated values?
is there a easier way to solve this?
def riddle(x):
list=[]
i=0
for i in range(0,len(x)):
for j in range(i,len(x)):
for k in range(j,len(x)):
if ((x[i]+x[j]+x[k]) ==30) and x[i]!=x[j]!=x[k]:
list.append((x[i],x[j],x[k]))
i = i+1
j= j+1
k = k+1
return(list)
print(riddle(x))
x= [2,3,5,8,6,89,20,15,7]

def riddle(x):
ls = []
for i in range(len(x)):
for j in range(i+1,len(x)):
for k in range(j+1,len(x)):
u = x[i]+x[j]+x[k]
if u==30:
ls.append([x[i],x[j],x[k]])
return ls
x = [2,3,5,8,6,89,20,15,7]
riddle(x)
Out[58]: [[2, 8, 20], [3, 20, 7], [8, 15, 7]]

First of all, don't use the name 'list' for a list as it's a keyword. I am going with list1 instead.
To get your answer, replace return(list1) with return(set(list1)) to remove duplicates. If you want the answer as a list and not a set, do return(list(set(list1)))
(This will not be possible unless u rename your list to list1)
Code:
def riddle(x):
list1=[]
i=0
for i in range(0,len(x)):
for j in range(i,len(x)):
for k in range(j,len(x)):
if ((x[i]+x[j]+x[k]) ==30) and x[i]!=x[j]!=x[k]:
list1.append((x[i],x[j],x[k]))
i = i+1
j= j+1
k = k+1
return(list(set(list1)))
x= [2,3,5,8,6,89,20,15,7]
print(riddle(x))
Output
[(2, 8, 20), (8, 15, 7), (3, 20, 7)]

Related

How to print list of numbers in square matrix?

l1 = [4, 8, 12,16,3,7,11,15,2,6,10,14,1,5,9,13]
output :
[4,8,12,16]
[3,7,5,11]
[1,6,10,14]
[1,5,9,13]
m =4
n=4
tmp = [[0]*m]*n
a = 0
for i in range(m):
for j in range(n):
tmp[i][j] = l1[a]
a += 1
not printing in required format.
What's wrong here ? Can you please help me.
You could achieve this with the following list of comprehension:
list1 = [4, 8, 12,16,3,7,11,15,2,6,10,14,1,5,9,13]
[list1[x:x+4] for x in list(range(0,len(list1),4))]
Output
[[4, 8, 12, 16], [3, 7, 11, 15], [2, 6, 10, 14], [1, 5, 9, 13]]
The issue with the code is the array initialization part.
tmp = [[0]*m]*n This will create a common memory address and whatever changes you are making to one index will be reflected to other index as well.
So to initialize the list you can use the following code
tmp = [[0 for _ in range(m)] for _ in range(n)]
The simple method is already shared by #Sebastien D
You just need to change the way you initialize your tmp matrix
tmp = [[[0] for _ in range(m)] for _ in range(n)]
Iterate through the initial list with step of m and every time append list of m elements to the final list where m is number of elements in each row.
t = []
for i in range(0, len(l1), m):
t.append(l1[i:i+m])
print(t)

matrix addition giving wrong answer

I am from java background, I am learning python matrix operation. I have an assignment question to add two matrices manually I can't figure out the error in my logic. need help thank you
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0] * col] * row
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print()
print(ans)
output :
[[11, 13, 18], [11, 13, 18], [11, 13, 18]]
The problem is here:
ans = [[0]*col]*row
This statement creates row number of objects, where each object is [[0]*col]. What this means is that, each "sub-list" in the list is pointing to the same list.
(More information about this behaviour here: List of lists changes reflected across sublists unexpectedly)
You can verify that by checking the id values of ans[0],ans[1] and so on:
>>> a = [[0]*col]*row
>>>
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> id(a[0])
140336190913992
>>> id(a[1])
140336190913992
>>> id(a[2])
140336190913992
This means, if we set a[0][1] = 10 (say), then EACH sub-list will have the the value 10 set. This is because all the lists point to the same list.
i.e.
>>> a[0][1] = 10
>>> a
[[0, 10, 0], [0, 10, 0], [0, 10, 0]]
Now, how do we avoid this?
You can do so by initiliasing the ans list in a different way, as in:
b = [[0 for x in range(col)] for y in range(row)]
You can verify that all the sub-lists point to different addresses by using id again:
>>> id(b[0])
140336190512520
>>> id(b[1])
140336190765000
>>> id(b[2])
140336197031816
So now if you run your original program, you will get desired results.
TLDR; your modified program looks like this:
x = [[12,7,3],[4 ,5,6],[7 ,8,9]]
y = [[5,8,1],[6,7,3],[4,5,9]]
row = len(x)
col = len(x[0])
ans = [[0 for x in range(col)] for y in range(row)]
for i in range(len(x)):
for j in range(len(x[i])):
ans[i][j] = x[i][j] + y[i][j]
print(ans)

Detect ranges of integers in a list in python

I am trying to write a function "detect_range" which detects ranges of integers from a list let's say:
a = [2, 4, 5, 6, 7, 8, 10, 12, 13]
import itertools
def detect_range(L):
for i, j in itertools.groupby(enumerate(L), lambda x: x[1] - x[0]):
j = list(j)
yield j[0][1], j[-1][1]
print(list(detect_range(a)))
It prints:
[(2, 2), (4, 8), (10, 10), (12, 13)]
However, I do not want the single integer like 2 and 10 to be printed in a pair, but single. So the output which I am looking from this code is:
[2, (4, 9), 10, (12, 14)]
If you insist on using itertools, you should add an if-statement to differenciate between the different cases.
To make the code more readable, I added the temporal variables start and length.
import itertools
def detect_range(L):
for i, j in itertools.groupby(enumerate(L), lambda x: x[1] - x[0]):
j = list(j)
start = j[0][1]
length = len(j)
if length == 1:
yield start
else:
yield (start, start+length)
print(list(detect_range(a)))
[2, (4, 9), 10, (12, 14)]
Otherwise, you could scrap itertools and simply implement your own algorithm:
def detect_range(input_list):
start = None
length = 0
for elem in input_list:
# First element
if start is None:
start = elem
length = 1
continue
# Element in row, just count up
if elem == start + length:
length += 1
continue
# Otherwise, yield
if length == 1:
yield start
else:
yield (start, start+length)
start = elem
length = 1
if length == 1:
yield start
else:
yield (start, start+length)
print(list(detect_range(a)))
[2, (4, 9), 10, (12, 14)]
Change it to
if j[0][1] == j[-1][1]:
yield j[0][1]
else:
yield j[0][1], j[-1][1]
You can change the yield statement to have a condition -
def detect_range(L):
for i, j in itertools.groupby(enumerate(L), lambda x: x[1] - x[0]):
j = list(j)
yield (j[0][1], j[-1][1]) if j[0][1]!=j[-1][1] else j[0][1]
Output:
[2, (4, 8), 10, (12, 13)]
Also the expected output is different from the given output (apart from single 2 and 10). So, this code assumes that it was a typo

How do I make this matching list code more efficient?

I have two lists. I want to get matching indices. I have come up with the following to illustrate as an example:
a = [1,2,6,5,3,4]
b = [1,3,4,2,5,6]
for i in range(len(a)):
for j in range(len(b)):
if b[j] != a[i]:
next
else:
print(i, j)
Seems fairly straightforward, but a bit long. Can anyone help me make this code more efficient?
Output:
0 0
1 3
2 5
3 4
4 1
5 2
a = [1,2,6,5,3,4]
b = [1,3,4,2,5,6,1,2,3,4,5,6]
b_dict = {}
for i, n in enumerate(b):
if n not in b_dict:
b_dict[n] = []
b_dict[n].append(i)
for i in range(len(a)):
if a[i] in b_dict:
for index in b_dict[a[i]]:
print(i, index)
O(a+b) solution, since "in" in a dict is O(1)
update verion allow match duplicate number in b
You could use a list comprehension like so:
>>> a = [1,2,6,5,3,4]
>>> b = [1,3,4,2,5,6]
>>>
>>> [[i,j] for i,k in enumerate(a) for j,v in enumerate(b) if k==v]
[[0, 0], [1, 3], [2, 5], [3, 4], [4, 1], [5, 2]]
Tips
If you have a loop that uses indices and their respective values, use enumerate instead of range(len()) and indexing.
In this case you don't need to bother with the non-matching condition (if b[j] != a[i]).
>>> for i, v0 in enumerate(a):
... for j, v1 in enumerate(b):
... if v0 == v1:
... print(i, j)
...
0 0
1 3
2 5
3 4
4 1
5 2
As a list comprehension:
>>> [(i, j) for i, v0 in enumerate(a) for j, v1 in enumerate(b) if v0 == v1]
[(0, 0), (1, 3), (2, 5), (3, 4), (4, 1), (5, 2)]
(I outputted tuples cause they seem to make more sense in this context.)

removing list with all values 0 from multidimensional list in python

a= [[0,0,0,0],[1,2,3,4],[5,6,7,8],[0,0,0,0],[0,0,0,0],[10,20,30,40],[0,0,0,0]]
for i in a:
if all([ v == 0 for v in i]):
a.remove(i)
print(a)
The output it gives is
[[1,2,3,4],[5,6,7,8],[10,20,30,40],[0,0,0,0]]
I don't figure out why it is not removing the last list with values zeros.
You're missing a tiny detail - you'll need to iterate in reverse.
for i in reversed(range(len(a))):
if all(v == 0 for v in a[i]):
del a[i]
print(a)
[[1, 2, 3, 4], [5, 6, 7, 8], [10, 20, 30, 40]]
By iterating forward, you're shrinking the list in size, so the loop never ends up iterating over the list completely (since you shrunk the list).
The below code would help
new_a = [l for l in a if set(l) != {0}]

Resources