Python - Appending list to another list - python-3.x

I am try to code a game which has a 3x3 grid (think noughts & crosses [US=Tic Tac Toe]).
Each cell has a weighting. When the player places a counter a score is calculated. I want my code to go through the 3x3 matrix and find the top score and return the co-ordinates of the cell where that top score is found (this works) - but if there are several cells with an equal top score I want to return a list containing each of the places where that score is found.
Here is a cut-down version of my code (with LOTS of print statements to try to work out why it's not working).
The intention is that the loop records a simple list ("pos") which has the row and column co-ordinates (e.g. [0][2]) and appends this to a running list of equal scores ("possibles")
If instead of trying to append a 2-entry list I put in a single random number, the overall list ("possibles") builds as expected, but appending the 2-entry list results in a duplicated list of the final position (see output).
I clearly have a logic problem, but I am new to Python. Can anyone show me where I have gone wrong?
def test():
val = 1
max_val = 0
possibles = [] # This is the list where I will store a list of equally weighted positions
pos = [] # This is simply a 2 number co-ordinate
pos.append("") # Get it ready for row & col references
pos.append("")
for row in range (0,3):
for col in range (0,3):
print("Testing row",row,"col",col)
print("Possibles so far",possibles)
print("Pos=",pos)
pos[0] = row
pos[1] = col
print("Now pos=",pos)
#possibles.append(randint(0,100)) # This works
possibles.append(pos) # This doesn't
print("List of equals",possibles)
test()
Output:
Testing row 0 col 0
Possibles so far []
Pos= ['', '']
Now pos= [0, 0]
Testing row 0 col 1
Possibles so far [[0, 0]]
Pos= [0, 0]
Now pos= [0, 1]
Testing row 0 col 2
Possibles so far [[0, 1], [0, 1]]
Pos= [0, 1]
Now pos= [0, 2]
Testing row 1 col 0
Possibles so far [[0, 2], [0, 2], [0, 2]]
Pos= [0, 2]
Now pos= [1, 0]
Testing row 1 col 1
Possibles so far [[1, 0], [1, 0], [1, 0], [1, 0]]
Pos= [1, 0]
Now pos= [1, 1]
Testing row 1 col 2
Possibles so far [[1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]
Pos= [1, 1]
Now pos= [1, 2]
Testing row 2 col 0
Possibles so far [[1, 2], [1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]
Pos= [1, 2]
Now pos= [2, 0]
Testing row 2 col 1
Possibles so far [[2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0], [2, 0]]
Pos= [2, 0]
Now pos= [2, 1]
Testing row 2 col 2
Possibles so far [[2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1]]
Pos= [2, 1]
Now pos= [2, 2]
List of equals [[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]

You append the same object pos over and over again to your list. If you change its value in the next loop, all its representations are changed as well. You can test this. Append at the end of your test function:
for item in possibles:
print(item, id(item))
See, all list items have the same id.
To avoid this, assign a new object in each loop:
def test():
possibles = []
for row in range (3):
for col in range (3):
pos = [row, col] #create a new list
print("Now pos=",pos)
possibles.append(pos) #and append this new element
print("List of equals",possibles)
test()
It looks similar, but instead of changing element [0] and [1] of an existing list pos, now in each loop a new list is created. If you check it with id(item) from above, all list elements of possibles have now a different id.

Related

Deleting an item from a list which is a value in a given dictionary

myDict={0:[1,2,3,4],1:[0,2],2:[0,1],3:[0,4],4:[0,3]}
Hi, being new to the concept of dictionaries I am unable to figure out how to delete an item from the list of any key value pair. Lets say I am on myDict[0], my concern is how do I delete lets say the values 1 and 2 of 0:[1,2,3,4] list. Thank you!
myDict = {0: [1, 2, 3, 4], 1: [0, 2], 2: [0, 1], 3: [0, 4], 4: [0, 3]}
myDict[0] = [3, 4] # Whatever here
'''
You can treat myDict[0] as a normal list
'''
myDict[0].remove(3) # Same as list.remove(), because myDict[0] is just a list
print(myDict[0])
print(myDict[0][0])# Printing the 0th value in the list, which is myDict[0]
myDict = {0: [1, 2, 3, 4], 1: [0, 2], 2: [0, 1], 3: [0, 4], 4: [0, 3]}
myDict[0].remove(myDict[0][0])
myDict[0].remove(myDict[0][1])
print(myDict)

Two loop with restriction [1,2] and [2,1] not acceptable python

I have two for loop to select items from a list and don't want to repeat [1,2] and [2,1] similar is the case for other elements. Basically I have
for i in range(0,20):
for j in range(0,20):
if (i != j):
function(list[i],list[j])
The output from [1,2] and [2,1] gives the same results and I don't want to repeat that. basically i and j are identical array. I eliminate similar elements using if loop.And I want to eliminate repeated elements.
Simply start your j loop from i.
lis = []
for i in range(0, 5):
for j in range(i + 1, 5):
lis.append([i, j])
This outputs
[[0, 1],
[0, 2],
[0, 3],
[0, 4],
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4]]
For a smaller output, I changed 20 to 5.

Indices of sorted array

I have a 2 dimensional Array with shape (nrows,ncols) containing real numbers. I would like get the indices (row,col) corresponding to the Array values in decreasing order. Checking the documentaion of np.argsort(), it seems that it only returns the indices ordered by a specific axis. Im sure that that this should be simple but i just cant figure it out.
For example, if i have:
[
[1 5 6]
[7 4 9]
[8 2 3]
]
the desired output would be:
[
(1,2),
(2,0),
(1,0),
(0,2),
(0,1),
(1,1),
(2,2),
(2,1),
(0,0),
]
Here's one way for descending order -
In [19]: a
Out[19]:
array([[1, 5, 6],
[7, 4, 9],
[8, 2, 3]])
In [20]: np.c_[np.unravel_index(a.ravel().argsort()[::-1],a.shape)]
Out[20]:
array([[1, 2],
[2, 0],
[1, 0],
[0, 2],
[0, 1],
[1, 1],
[2, 2],
[2, 1],
[0, 0]])
For ascending order, skip the flipping part : [::-1].
Or with negative values -
In [24]: np.c_[np.unravel_index((-a).ravel().argsort(),a.shape)]
Out[24]:
array([[1, 2],
[2, 0],
[1, 0],
[0, 2],
[0, 1],
[1, 1],
[2, 2],
[2, 1],
[0, 0]])

Adding sublist to list in python3 not working

I have a really weird issue in Python3. I have some code that generates some different list from a list of integers (what this does exactly is not relevant).
def get_next_state(state):
max_val = max(state)
max_index = state.index(max_val)
new_state = state
for n in range(max_val + 1):
new_state[max_index] -= 1
new_state[(n + max_index) % len(state)] += 1
return new_state
Now all I want to do is add a next state to some list that keeps the states. This is my code:
l = [0, 2, 7, 0]
seen_states = []
for _ in range(10):
print(l)
seen_states += [l]
l = get_next_state(l)
print(seen_states)
For some reason list l is assigned correctly when I print it, but it is not added correctly to the list of seen states. Note that I have also tried seen_states.append(l) instead of using += [l]. Does anyone know why this happend?
To prevent these problems use copy, deepcopy or list[:]
import copy
def get_next_state(state):
max_val = max(state)
max_index = state.index(max_val)
new_state = copy.deepcopy(state)
for n in range(max_val + 1):
new_state[max_index] -= 1
new_state[(n + max_index) % len(state)] += 1
return new_state
You are sending your list l inside the function. When you assign it to another name, you are not making a copy but referencing the original object. Any modification on these lists is a change in the original object.
Using new_state = state[:] (copies the list instead of referencing the original) in the get_next_state produces the following output:
[0, 2, 7, 0]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[3, 1, 2, 3]
[0, 2, 3, 4]
[1, 3, 4, 1]
[2, 4, 1, 2]
[[0, 2, 7, 0], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2], [3, 1, 2, 3], [0, 2, 3, 4], [1, 3, 4, 1], [2, 4, 1, 2]]
Not sure if this is your desired output, as you did not specify what you are getting as "wrong" output

multilist = [[0 for col in range(colNum)]for row in range(rowNum)]

Can someone please elaborate how it is functioning?
Like I am taking a value (3,3)
colNum is 3 and rowNum is 3.
multilist = [[0 for col in range(colNum)]for row in range(rowNum)]
prints '0' in specified number of columns and rows.
ex: if colNum is 4 and rowNum is 4... then you will notice a multilist like below.
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Here in the list comprehending statement the syntax is
[ [ output_expression() for(set of columns to iterate) ]for(set of rows to iterate)]
And 0 is your outputexpression.
Now another example, in which your output expression is adding row index and column index
multilist = [[col+row for col in range(4)]for row in range(4)]
and the output is
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
def print_multilist(rowNum, colNum):
multilist = [[0 for col in range(colNum)]for row in range(rowNum)]
print(multilist)
print_multilist(3,3)#prints [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print_multilist(2,2) #prints [[0, 0], [0, 0]]
The above line is a list comprehension. It is equivalent to as follows without using list comprehensions
def print_multilist(rowNum, colNum):
multilist = []
for row in range(rowNum):
multilist.append([])
for col in range(colNum):
multilist[row].append(0)
print(multilist)
print_multilist(3,3) #prints [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print_multilist(2,2) #prints [[0, 0], [0, 0]]
List comprehensions are very useful in python, as they decreases the code written like above. For more information about list comprehensions, Visit link

Resources