python updating global dict inside recursive function - python

I am trying to find all permutations of elements in a list and add it to a global dictionary
Code:
outp={}
k=0
def func(i,arr):
global outp
global k
arr=arr.copy()
for j in range(i,len(list)):
arr[i],arr[j] = arr[j],arr[i]
if i!=j or i==0:
k=k+1
print("\n\n",arr,k)
outp[k]=arr
print("\n",outp)
func(i+1,arr)
list = [1,2,3,8]
func(0,list)
Output below:
Till 4th element it updated correctly. During 5th element, it updated both 5th and 3rd element in the dictionary. I don't know why it is happening. Kindly help
[1, 2, 3, 8] 1
{1: [1, 2, 3, 8]}
[1, 2, 8, 3] 2
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3]}
[1, 3, 2, 8] 3
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8]}
[1, 3, 8, 2] 4
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 3, 2, 8], 4: [1, 3, 8, 2]}
[1, 8, 2, 3] 5
{1: [1, 2, 3, 8], 2: [1, 2, 8, 3], 3: [1, 8, 2, 3], 4: [1, 3, 8, 2], 5: [1, 8, 2, 3]}

You need to place a copy of the array in the dictionary:
outp[k] = arr.copy()

This would be a better way to copy list to a new list.
arr=arr[:] .
https://repl.it/repls/BronzeYellowConversion

Related

Convert lists into higher dimension so that elements can be reached by following

I have a matrix that I want to convert to 3D so that I can be able to print the element of list[i][j][k]
a = [[[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [2, 3, 2, 3, 4,5], [3, 2, 3, 4, 3, 4], [4, 3, 4, 5, 4, 3], [5, 4, 5, 6, 5, 4]]]
print(a[5][5][0]) # I want to be able to print in 3D`
I get right output if I do a[5][5] but wrong when I add the [0]. Is there anyway of converting my matrix such that this will be solved?
I tried to just wrap the list up with brackets [list], but it did not work. I also did:
b = [[i] for i in a]
which gave me [[[0,1,2,3,4,5]],[[1,2,3,4,5,6]],...
and it still did not work!
NOTE: I want the i to be the row, j to be the column and k to be 0 or 1, so k = 0 (in which case the value is the row index of the cell is pointing to), or the k = 1 (the value is the column index).
Tried to reproduce your issue. To me, it works if you use the right index. Here, it perfectly works if you do for instance
print(a[0][0][5]) # I want to be able to print in 3D`
for list a = [[[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [2, 3, 2, 3, 4,5], [3, 2, 3, 4, 3, 4], [4, 3, 4, 5, 4, 3], [5, 4, 5, 6, 5, 4]]] you have just a[0][n][n]. You can try a[0][5][5]
You have index like below:
a = [
#0 element i
[
#0 element j
[0, 1, 2, 3, 4, 5],
#1 element j
[1, 2, 3, 4, 5, 6],
#2 element j
[2, 3, 2, 3, 4,5],
#3 element j
[3, 2, 3, 4, 3, 4],
#4 element j
[4, 3, 4, 5, 4, 3],
#5 element j
[5, 4, 5, 6, 5, 4]
]
]
print(a[0][5][5]) # a[i][j][k]

Python: How to aggregate and count identical values in a Dictionary

I'm using a defaultdict from Python's collections:
from collections import defaultdict
data = defaultdict(list)
Within the dictionary I have a set of key/list. Example:
{1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
I'm looking for a way to count how many times each list (identical order and content) is found in the dictionary. Basically, I need to aggregate each list with a counter.
For example, the combination [1, 6, 3, 4, 5] is found 2 times.
Is there any helper class/function that can do it? Other than that, I'd just create a double for loop across the dictionary.
Thanks!
Try this:
from collections import Counter
data = defaultdict(list, {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]})
c = Counter(map(tuple, data.values()))
print(c)
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})
H = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
occurences = dict()
for i in H.keys() :
k = 0
for j in H.keys():
if H[j] == H[i] :
k += 1
if i not in occurences.keys():
occurences[i] = k
Use collections.Counter
>>> from collections import Counter
>>> d = {1: [1, 6, 3, 4, 5], 2: [1, 3, 2, 4, 5], 3: [1, 6, 3, 4, 5]}
>>> print(Counter(tuple(l) for l in d.values())
Counter({(1, 6, 3, 4, 5): 2, (1, 3, 2, 4, 5): 1})
You'll have to convert your lists to tuples, because Counters can't count unhashable (mutable) types.

Form groups in a list based on condition

(Edited based on feedbacks)
I've got a list like this:
my_list = [1,2,3,1,2,4,1,3,5,1,4,6,1,4,7]
That I'm struggling to turn into that:
result = [[1,2,3,1,2,4],[1,3,5],[1,4,6,1,4,7]]
I want to group my_list elements in sublists of 3 elements unless my_list[i] = my_list[i+3] in this case I want to merge those in bigger sublists.
Here is what I've tried:
result = []
for i in range(1,len(my_list),3):
try:
print(my_list[i],my_list[i+3])
if my_list[i] == my_list[i+3]:
result.extend(my_list[i-1:i+5])
else:
result.append(my_list[i-1:i+2])
FWIW, the description of your logic isn't quite clear. However, if I understand your code correctly, I think this is at least something in the correct direction:
def stepper(my_list, step, bigger_step):
res = []
idx = 0
while idx <= len(my_list)-1:
if idx + step > len(my_list)-1:
# Remove this append if you don't want the "leftovers"
res.append(my_list[idx:])
break
if my_list[idx] != my_list[idx+step]:
res.append(my_list[idx:idx+step])
idx += step
else:
res.append(my_list[idx:idx+bigger_step])
idx += bigger_step
return res
my_list = [1,2,3,1,2,4,1,3,5,1,3,6,1,2,7]
print(stepper(my_list, step=3, bigger_step=6)) # Output: [[1, 2, 3, 1, 2, 4], [1, 3, 5, 1, 3, 6], [1, 2, 7]]
Note that the above output is different from your given example, because of your given logic that you've provided makes the second sub-list extended as well as the first.
Using the above code, we can check the results if we change bigger_step easily with a for-loop:
for big in range(4, 10):
print(f"Step: 3, Bigger_Step: {big}, Result:{stepper(my_list, step=3, bigger_step=big)}")
Output:
Step: 3, Bigger_Step: 4, Result:[[1, 2, 3, 1], [2, 4, 1], [3, 5, 1, 3], [6, 1, 2], [7]]
Step: 3, Bigger_Step: 5, Result:[[1, 2, 3, 1, 2], [4, 1, 3], [5, 1, 3], [6, 1, 2], [7]]
Step: 3, Bigger_Step: 6, Result:[[1, 2, 3, 1, 2, 4], [1, 3, 5, 1, 3, 6], [1, 2, 7]]
Step: 3, Bigger_Step: 7, Result:[[1, 2, 3, 1, 2, 4, 1], [3, 5, 1, 3, 6, 1, 2], [7]]
Step: 3, Bigger_Step: 8, Result:[[1, 2, 3, 1, 2, 4, 1, 3], [5, 1, 3], [6, 1, 2], [7]]
Step: 3, Bigger_Step: 9, Result:[[1, 2, 3, 1, 2, 4, 1, 3, 5], [1, 3, 6, 1, 2, 7]]

Creating a dictionary given values from a list and dictionary

So, I am given a list
a =[[[0, 0, 3, 3, 3, 3], [0, 0, 1, 3, 3, 3, 3]], [[0, 1]], [[2, 2, 2, 3, 3, 3, 3], [2, 2, 2, 3, 3, 3, 3], [2, 2, 2, 3, 3, 3, 3]], [[0, 0, 2, 2, 2, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3, 3]]]
and a dictionary d.
d = {0:2,1:1,2:3,3:4}
For the output, I want a dictionary:
output = {0:[0,3],1;[1],2:[2,3],3:[0,2]}
This output is formed by passing through each sublist of a and checking the number of times each element appears in d.
Let's look at index 0 of a. Now we look at a[0][0]and
a[0][1] and since 0 appears twice in both and 3 appears 4 times (comparing it to d), [0,3] are added to index 0. Similarly, at index 1, 0 appears just once and is not added to the dictionary at index 1.
What I tried so far:
def example(a,d):
for i in range(len(a)):
count = 0
for j in range(len(a[i])):
if j in (a[i][j]):
count+=1
if count == d[i]:
print(i,j)
Edit: A version that work
from collections import Counter
a = [[[0, 0, 3, 3, 3, 3], [0, 0, 1, 3, 3, 3, 3]], [[0, 1]],
[[2, 2, 2, 3, 3, 3, 3], [2, 2, 2, 3, 3, 3, 3], [2, 2, 2, 3, 3, 3, 3]],
[[0, 0, 2, 2, 2, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3, 3], [0, 0, 2, 2, 2, 3, 3, 3, 3]]]
d = {0: 2, 1: 1, 2: 3, 3: 4}
output = {i: [] for i in range(len(a))}
for j, sublist in enumerate(a):
counts = [Counter(i) for i in sublist]
for k,v in d.items():
try:
if all(counts[i][k] == v for i in range(len(counts))):
output[j].append(k)
except: continue
print(output)
output:
{0: [0, 3], 1: [1], 2: [2, 3], 3: [0, 2]}
The try except block is merely for convenience, If you insist you can if your way around this by checking if a key is in all counters (which is a requirement for it to be add)

Python consecutive operations on list getting executed in wrong order

I have a function written in python that performs some consecutive operations on two lists. The problem is that at random times during the execution of these functions, they give wrong answer. The code inside the function is
def temp(c, p):
random.seed(0)
x = random.randint(0 , len(c)-1)
y = random.randint(0 , len(c)-1)
s_1 = c[x][0]
s_2 = c[y][0]
p[x] += [s_1]
p[y] += [s_2]
p[x].remove(s_2)
p[y].remove(s_1)
c[x], c[y] = c[y], c[x]
return c, p
def anotherFunction():
iter = 1000
for i in iter:
c_main, p_main = temp(c, p)
I have a list of list with numbers ranging from 0 to n. For example c contains the following
c = [[7], [6], [1], [2], [5], [4], [0], [3]]
And p is also a list of list that contains all the numbers from 0 to n except that at index which are there in c.
p = [[0, 2, 4, 6, 5, 1, 3]
[0, 1, 2, 3, 4, 5, 7]
[0, 2, 3, 4, 6, 7, 5]
[0, 1, 3, 5, 6, 7, 4]
[0, 2, 4, 6, 7, 3, 1]
[0, 1, 2, 3, 6, 7, 5]
[1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 4, 5, 6, 7]]
This is how the values should be at any random point in the function. That is the values at idx in c should not be present in the list at idx in p.
But sometimes during the execution of the function, the values selected by x and y are swapped but one other value also gets affected. This is how the two list looks like sometimes
c = [[3], [1], [4], [5], [7], [0], [2], [6]]
p = [[0, 1, 2, 4, 5, 6, 7]
[0, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 6, 7, 4]
[0, 1, 2, 3, 6, 5, 5]
[0, 1, 2, 3, 4, 6, 7]
[1, 2, 3, 4, 6, 7, 5]
[0, 1, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 7]]
I'm unable to understand how these consecutive operations are getting affected by one another. This function gets called inside a loop of another function.
UPDATE:
I debugged my code more carefully and realized that at some iterations of the for loop two more values get swapped in c in addition to x and y. And because these values get swapped but they are not updated in p in some executions I get a faulty output. Any ideas why two more values are getting swapped.
Your code is not complete.
You seam to call your function like this:
c = [[3], [1], [4], [5], [7], [0], [2], [6]]
p = [[0, 1, 2, 4, 5, 6, 7],
[0, 2, 3, 4, 5, 6, 7],
[0, 1, 2, 3, 6, 7, 4],
[0, 1, 2, 3, 6, 5, 5],
[0, 1, 2, 3, 4, 6, 7],
[1, 2, 3, 4, 6, 7, 5],
[0, 1, 3, 4, 5, 6, 7],
[0, 1, 2, 3, 4, 5, 7]]
for i in range(1000):
c_main, p_main = temp(c, p)
note: if fixed your code: add range and add comma for each lines in p.
But inside your temp() function, your are modifying the content of p.
So, you may not have what you expect. Because you reuse the same p at each iteration. So sometimes it becomes inconsistent.
What you want, is certainly something like that:
import random
def temp(c):
# -- raw matrix
p = [[col for col in range(8)] for row in range(len(c))]
# -- drop a number
for p_row, c_row in zip(p, c):
p_row.pop(c_row[0])
# -- shuffle
for row in p:
random.shuffle(row)
return p
You can use it like this:
cols = [[3], [1], [4], [5], [7], [0], [2], [6]]
print(temp(cols))
You get:
[[6, 1, 4, 5, 7, 2, 0],
[3, 0, 5, 4, 2, 7, 6],
[2, 7, 0, 3, 6, 5, 1],
[1, 2, 7, 4, 6, 3, 0],
[3, 1, 4, 6, 2, 0, 5],
[4, 5, 6, 3, 7, 1, 2],
[0, 6, 1, 5, 7, 3, 4],
[4, 3, 7, 0, 1, 5, 2]]

Categories

Resources