Python consecutive operations on list getting executed in wrong order - python

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

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]

How do I roll 4 dice 6 different times and have the output of all 6 iterations?

So what I'm trying to do is be able to roll 6 sets of 4 individual 6 sided dice. The current code that I currently have is:
import random
stat_rolls = []
for i in range(6):
for j in range(4):
num = random.randint(1, 6)
stat_rolls.append(num)
print(stat_rolls)
Currently the output is as follows:
[5, 6, 5, 2, 5, 6, 2, 2, 4, 6, 3, 1, 3, 5, 5, 3, 5, 5, 6, 4, 3, 4, 1, 4]
What I actually want the output to look like is the following:
[5, 6, 5, 2]
[5, 6, 2, 2]
[4, 6, 3, 1]
[3, 5, 5, 3]
[5, 5, 6, 4]
[3, 4, 1, 4]
How would this be possible? Would it be through a dict function? I'm still learning Python so any kind of help would be much appreciated!!
One really basic whay of achieving what you want is to create a buffer array that gets filled with a cycle of trows and then appending it to an upper array to get the desired format:
import random
stat_rolls = []
buffer=[]
for i in range(6):
buffer=[]
for j in range(4):
num = random.randint(1, 6)
buffer.append(num)
stat_rolls.append(buffer)
print(stat_rolls)
this outputs:
[[4, 4, 6, 1], [1, 4, 2, 3], [3, 5, 3, 3], [3, 2, 5, 2], [6, 3, 5, 4], [3, 2, 5, 1]]
you can then change your print format to get to different print layouts,for example,if you print it out as:
for i in stat_rolls:
print(i)
you get:
[6, 4, 1, 4]
[3, 5, 2, 1]
[5, 1, 5, 6]
[6, 4, 1, 3]
[4, 6, 6, 2]
[5, 2, 3, 3]

sample n random permutations of a list in python [duplicate]

This question already has answers here:
python shuffling with a parameter to get the same result
(4 answers)
Closed 1 year ago.
I have a list of values such as:
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
and I need to reproducibly return n random shuffles of this list.
Ideally, I need a function with seed such that f(lst, samples = 2, seed = 1234)
-> return two shuffles of the list lst such as:
[5, 7, 1, 6, 2, 8, 0, 4, 3, 9]
[8, 7, 3, 0, 1, 4, 5, 9, 6, 2]
Repeated execution of this function (with the same seed) would return the same two lists.
This works without numpy:
import sys
import random
some_seed = 123 # change this to get different shuffles
def n_shuffles(lst, n):
r = random.Random(some_seed)
for _ in range(n):
_l = lst[:]
r.shuffle(_l)
yield _l
l = list(range(10))
>>> [*n_shuffles(l, 3)]
[[8, 7, 5, 9, 2, 3, 6, 1, 4, 0], [7, 6, 3, 4, 1, 0, 2, 5, 9, 8], [1, 8, 5, 6, 4, 7, 9, 0, 2, 3]]
>>> [*n_shuffles(l, 3)]
[[8, 7, 5, 9, 2, 3, 6, 1, 4, 0], [7, 6, 3, 4, 1, 0, 2, 5, 9, 8], [1, 8, 5, 6, 4, 7, 9, 0, 2, 3]]
You can use np.copy
import numpy as np
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def shuffle_list(arr:list,samples:int,seed:int):
np.random.seed(seed)
res = []
for i in range(samples):
arr_copy=np.copy(arr)
np.random.shuffle(arr_copy)
res.append(arr_copy)
return res
#test
print(shuffle_list(lst,2,1234))
output:
[array([7, 2, 9, 1, 0, 8, 4, 5, 6, 3]), array([7, 3, 5, 1, 4, 8, 0, 2, 6, 9])]
Ok, it wasn't an exact duplicate, but the proposed topic has pretty much shown that re-setting the seed() is the key:
import random
def shuffles(l,n):
random.seed(4) # just the same one as in the referred topic
return [random.sample(l,k=len(l)) for i in range(n)]
print(shuffles([1,2,3,4],3))
print("again:")
print(shuffles([1,2,3,4],3))
will generate
[[2, 4, 1, 3], [4, 1, 3, 2], [1, 2, 3, 4]]
again:
[[2, 4, 1, 3], [4, 1, 3, 2], [1, 2, 3, 4]]

Problem involving 'alphabetization' of sets of row elements

Consider a variable setSize (it can take value 2 or 3), and a numpy array v.
The number of columns in v is divisible by setSize. Here's a small sample:
import numpy as np
setSize = 2
# the array spaces are shown to emphasize that the rows
# are made up of sets having, in this case, 2 elements each.
v = np.array([[2,5, 3,5, 1,8],
[4,6, 2,7, 5,9],
[1,8, 2,3, 1,4],
[2,8, 1,4, 3,5],
[5,7, 2,3, 7,8],
[1,2, 4,6, 3,5],
[3,5, 2,8, 1,4]])
PROBLEM: For the rows that have all elements unique, I need to ALPHABETIZE the sets.
For example: set 1,14 would precede set 3,5, which would precede set 5,1.
As a final step, I need to eliminate any duplicated rows that may result.
In this example above, the array rows having indices 1,3,5,and 6 have unique elements,
so these rows must be alphabetized. The other rows are not changed.
Further, the rows v[3] and v[6], after alphabetization, are now identical. One of them may be dropped.
The final output looks like:
v = [[2,5, 3,5, 1,8],
[2,7, 4,6, 5,9],
[1,8, 2,3, 1,4],
[1,4, 2,8, 3,5],
[5,7, 2,3, 7,8],
[1,2, 3,5, 4,6]]
I can identify the rows having unique elements with code like below, but I stuck with the alphabetization code.
s = np.sort(v,axis=1)
v[(s[:,:-1] != s[:,1:]).all(1)]
Assuming you have unsuitable rows dropped with:
s = np.sort(v, axis=1)
idx = (s[:,:-1] != s[:,1:]).all(1)
w = v[idx]
Then you can get orders of each row with np.lexsort on a reshaped array:
w = w.reshape(-1,3,2)
s = np.lexsort((w[:,:,1], w[:,:,0]))
Then you can apply fancy indexing and reshape it back:
rows, orders = np.repeat(np.arange(len(s)), 3), s.flatten()
v[idx] = w[rows, orders].reshape((-1,6))
If you need to drop duplicated rows, you can do it like so:
u, idx = np.unique(v, return_index=True, axis=0)
output = v[np.sort(idx)]
Visualization of process:
Sample run:
>>> s
array([[1, 0, 2],
[1, 0, 2],
[0, 2, 1],
[2, 1, 0]], dtype=int64)
>>> rows
array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3])
>>> orders
array([1, 0, 2, 1, 0, 2, 0, 2, 1, 2, 1, 0], dtype=int64)
>>> v[idx]
array([[2, 7, 4, 6, 5, 9],
[1, 4, 2, 8, 3, 5],
[1, 2, 3, 5, 4, 6],
[1, 4, 2, 8, 3, 5]])
>>> v
array([[2, 5, 3, 5, 1, 8],
[2, 7, 4, 6, 5, 9],
[1, 8, 2, 3, 1, 4],
[1, 4, 2, 8, 3, 5],
[5, 7, 2, 3, 7, 8],
[1, 2, 3, 5, 4, 6],
[1, 4, 2, 8, 3, 5]])
>>> output
array([[2, 5, 3, 5, 1, 8],
[2, 7, 4, 6, 5, 9],
[1, 8, 2, 3, 1, 4],
[1, 4, 2, 8, 3, 5],
[5, 7, 2, 3, 7, 8],
[1, 2, 3, 5, 4, 6]])

Select and compare every element in a column-list

I am trying to solve this puzzle question:
There is only one five-digit number n, such that every one of the following ten numbers share exactly one digit in common in the same position as n. Find n.
I'm trying to get like this:
https://i.stack.imgur.com/hufIc.jpg
For each column, selects every element and compares it along the column if it matches the same number. And then, appends it to get which number were matched on every column.
should i add if's in here:
L = [[0, 1, 2, 6, 5],
[1, 2, 1, 7, 1],
[2, 3, 2, 5, 7],
[3, 4, 5, 4, 8],
[4, 5, 9, 7, 0],
[5, 6, 2, 3, 6],
[6, 7, 3, 2, 4],
[7, 8, 0, 8, 4],
[8, 9, 8, 7, 2],
[9, 9, 4, 1, 4]]
for c in range(10):
for r in range(5):
print(L[c][r], end=' ')
print()
The easiest way I can think of is to get all the values of a column in a variable and then check if any value occurs more than once. The solution would look something like:
L = [
[0, 1, 2, 6, 5],
[1, 2, 1, 7, 1],
[2, 3, 2, 5, 7],
[3, 4, 5, 4, 8],
[4, 5, 9, 7, 0],
[5, 6, 2, 3, 6],
[6, 7, 3, 2, 4],
[7, 8, 0, 8, 4],
[8, 9, 8, 7, 2],
[9, 9, 4, 1, 4]
]
for r in range(5):
val = [L[c][r] for c in range(10)]
for i in range(10):
if val[i] in val[:i]:
print(val[i], end=" ")
break
else:
print(0, end=" ")
print()
L = [
[0, 1, 2, 6, 5],
[1, 2, 1, 7, 1],
[2, 3, 2, 5, 7],
[3, 4, 5, 4, 8],
[4, 5, 9, 7, 0],
[5, 6, 2, 3, 6],
[6, 7, 3, 2, 4],
[7, 8, 0, 8, 4],
[8, 9, 8, 7, 2],
[9, 9, 4, 1, 4]
]
for col_index in range(5):
col= [row[col_index] for row in L]
duplicate = [x for x in col if col.count(x) > 1]
if len(duplicate) == 0:
print(0, end=" ")
else:
print(duplicate[0], end=" ")
print()

Categories

Resources