appending to a list copies the last item python - python

I am trying to use a path finding algorithm and I want it to print all the steps one by one, this is a simplified code with only the important parts. For some reason this prints out 7 same levels that are only the final step, but I need it to print out all of the steps. The problem seems to be in the appending part, but I don't know how to fix it.
level = [
[">","#"," "," "],
[" ","#","#"," "],
[" "," ","#"," "],
["#"," "," "," "],
]
cycle = [[0,0],[1,0],[2,1],[3,2],[3,3],[2,3],[1,3],[0,2]]
output = []
for i in range(len(cycle)-1):
level[cycle[i ][0]][cycle[i ][1]] = " "
level[cycle[i+1][0]][cycle[i+1][1]] = ">"
output.append(level)
for i in output:
for ii in i:
print(ii)
print()
I need someone to solve this problem for me, as anything on this site doesn't work in my exact problem

import copy
level = [
[">","#"," "," "],
[" ","#","#"," "],
[" "," ","#"," "],
["#"," "," "," "],
]
cycle = [[0,0],[1,0],[2,1],[3,2],[3,3],[2,3],[1,3],[0,2]]
output = []
for i in range(len(cycle)-1):
level_copy = copy.deepcopy(level)
level_copy[cycle[i ][0]][cycle[i ][1]] = " "
level_copy[cycle[i+1][0]][cycle[i+1][1]] = ">"
output.append(level_copy)
for i in output:
for ii in i:
print(ii)
print()
When you do level[cycle[i ][0]][cycle[i ][1]] = " " inside the loop, you are referring to the same level object defined in the first line. So you do end up putting level multiple times, but they all are referring to the same object and hence contain the value that was written in the last iteration of loop.
level = []
output = []
for i in range (2):
if i == 0:
level.append(1)
level.append(2)
else
level.append(24)
level.append(25)
output.append(level)
i = 0: Start: level=[], end: level=[1,2]
i = 1: Start: level=[1,2] end: level=[1,2,24,25] // Observe that it starts with state left at end of first iteration as we are still referring to the same object in memory referred to by variable level.

Related

indexError out of range when there should not be

I have a long line of code that prints a bunch of symbols for graphics, and I just started getting an index out of range error. it is inside a function, and this the code that matters:
at top, after imports(fr termcolor cprint, colored , time, os, random)
rannum = random.randrange(1,20,1)
the function:
def obstacle():
rocknum = random.randrange(0,12,1)
rock = ["on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan","on_cyan"]
rock[rocknum]= "on_cyan"
ongroundls = [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "] #runframe 1 list
pos = rannum
#print(rannum)
if rannum == random.randrange(0,20,1):
#print(rannum, pos)
ongroundls[rannum] = "4"
rock[rocknum] = "on_yellow"
else:
rock[rocknum] = "on_cyan"
#print(colored(ongroundls[0],"grey","on_cyan")+colored(ongroundls[1],"grey","on_cyan")+colored(ongroundls[2],"grey","on_cyan")+colored(ongroundls[3],"grey","on_cyan")+colored(ongroundls[4],"grey","on_cyan")+colored(ongroundls[5],"grey","on_cyan")+colored(ongroundls[6],"grey","on_cyan")+colored(ongroundls[7],"grey","on_cyan")+colored(ongroundls[8],"grey","on_cyan")+colored(ongroundls[9],"grey","on_cyan")+colored(ongroundls[10],"grey","on_cyan")+colored(ongroundls[11],"grey","on_cyan")+colored(ongroundls[12],"grey","on_cyan")+colored(ongroundls[13],"grey","on_cyan")+colored(ongroundls[14],"grey","on_cyan")+colored(ongroundls[15],"grey","on_cyan")+colored(ongroundls[16],"grey","on_cyan")+colored(ongroundls[17],"grey","on_cyan")+colored(ongroundls[18],"grey","on_cyan")+colored(ongroundls[19],"grey",rock[0])+colored(ongroundls[20],"grey",rock[1])+colored(ongroundls[21],"grey",rock[2])+colored(ongroundls[22],"grey",rock[3])+colored(ongroundls[23],"grey",rock[4])+colored(ongroundls[24],"grey",rock[5])+colored(ongroundls[25],"grey",rock[6])+colored(ongroundls[26],"grey",rock[7])+colored(ongroundls[27],"grey",rock[8])+colored(ongroundls[28],"grey",rock[9])+colored(ongroundls[29],"grey",rock[10])+colored(ongroundls[30],"grey",rock[11])+colored(ongroundls[31],"grey",rock[12]))
while pos > 19:
ongroundls[pos] = "#"
pos - 1
if pos == random.randrange(0, 32, 1):
pos == random
print(colored(ongroundls[0],"grey","on_cyan")+colored(ongroundls[1],"grey","on_cyan")+colored(ongroundls[2],"grey","on_cyan")+colored(ongroundls[3],"grey","on_cyan")+colored(ongroundls[4],"grey","on_cyan")+colored(ongroundls[5],"grey","on_cyan")+colored(ongroundls[6],"grey","on_cyan")+colored(ongroundls[7],"grey","on_cyan")+colored(ongroundls[8],"grey","on_cyan")+colored(ongroundls[9],"grey","on_cyan")+colored(ongroundls[10],"grey","on_cyan")+colored(ongroundls[11],"grey","on_cyan")+colored(ongroundls[12],"grey","on_cyan")+colored(ongroundls[13],"grey","on_cyan")+colored(ongroundls[14],"grey","on_cyan")+colored(ongroundls[15],"grey","on_cyan")+colored(ongroundls[16],"grey","on_cyan")+colored(ongroundls[17],"grey","on_cyan")+colored(ongroundls[18],"grey","on_cyan")+colored(ongroundls[19],"grey",rock[0])+colored(ongroundls[20],"grey",rock[1])+colored(ongroundls[21],"grey",rock[2])+colored(ongroundls[22],"grey",rock[3])+colored(ongroundls[23],"grey",rock[4])+colored(ongroundls[24],"grey",rock[5])+colored(ongroundls[25],"grey",rock[6])+colored(ongroundls[26],"grey",rock[7])+colored(ongroundls[27],"grey",rock[8])+colored(ongroundls[28],"grey",rock[9])+colored(ongroundls[29],"grey",rock[10])+colored(ongroundls[30],"grey",rock[11])+colored(ongroundls[31],"grey",rock[12]))
in while loop (buffer is just a small delay and a os.system('cls')
obstacle()
buffer()
rannum = random.randrange(1,20,1)
it was working fine, then I made some minor changes and i cannot seem to fix it. i have tried changing the randrange, and some things are commented out in an attempt to fix it. , so the numbers are not what they were when the problem started. What could I do to fix it?
Your problem is the final line. You hard-coded rock[12] at the end of the print, but rock only has 12 elements, so the last valid index is 11.
As I noted in the comments, even if you fix this, the code is borked; your while loop will either never run, or never exit, because you never change pos within the loop (pos - 1 computes a new value, but never stores it; pos -= 1 is perhaps the intent).

How to make last element of list finish with a dot and the others with a comma?

I made this list with a for loop that points errors when yoy choose a name. I'd like to know how can I make it so that the last line finishes with '.' and the others finish with ';'.
while True:
if len(errors_list) != 0:
print("Your name has thesse errors::")
for i in errors_list:
print(" " + str(errors_list.index(i) + 1) + "- " + i + ".")
print("Try again.")
errors_list.clear()
name = input("My name is ").title()
choose_name(name)
else:
print("Nice to meet you, " + fname + " " + sname + ".")
break
Result when I type a name like '--- ':
Your name has these errors:
1- It has no letters.
2- It has symbols.
3- The last letter is a space.
Try again.
My name is
I'd like to make it so that 1 and 2 finish with ';' and 3 with '.'. Thanks!
All the existing solutions so far seem pretty poor, this is as print is expensive to call.
errors_list.index(i) runs in O(n) time making your solution run in O(n^2) time. You can improve this, to O(n) time, by using enumerate.
You can also think of what you're doing simply as concatenating values of a list and adding a period.
I would use:
errors = [f' {i}- {error}' for i, error in enumerate(errors_list, 1)]
print(';\n'.join(errors) + '.')
Extending Roman Perekhrest's answer, enumerate has an optional parameter start:
errors_list = ['It has no letters', 'It has symbols', 'The last letter is a space']
for i, err in enumerate(errors_list, start=1):
print("\t{}- {}{}".format(i, err, ';' if i < len(errors_list) else '.'))
additionaly with Python 3.6+ you can use f-strings instead of format:
errors_list = ['It has no letters', 'It has symbols', 'The last letter is a space']
for i, err in enumerate(errors_list, start=1):
print(f"\t{i}- {err}{';' if i < len(errors_list) else '.'}")
Instead of:
for i in errors_list:
print(" " + str(errors_list.index(i) + 1) + "- " + i + ".")
do
s = len(errors_list)
for e, i in enumerate(errors_list):
ending = ";" if e + 1 < s else "."
print(" " + str(errors_list.index(i) + 1) + "- " + i + ending)
EDIT:
to those jumping to the gun - OP did write in a title comma, but he used semicolon (;) twice (!) in a question itself.
Simply with enumerate function:
errors_list = ['It has no letters', 'It has symbols', 'The last letter is a space']
...
for i, err in enumerate(errors_list):
print(" {}- {}{}".format(i+1, err, ';' if i+1 != len(errors_list) else '.'))
The crucial loop will output:
1- It has no letters;
2- It has symbols;
3- The last letter is a space.

TypeError: list indices must be integers or slices, not tuple, Im very new and confused why my list of list doesn't work

theListofSalary = [
[" $0 - $9,999 ",": "]
["$10,000 - $19,999 ",": "]
["$20,000 - $29,999 ",": "]
["$30,000 - $39,999 ",": "]
["$40,000 - $49,999 ",": "]
["$50,000 - $59,999 ",": "]
["$60,000 - $69,999 ",": "]
["$70,000 - $79,999 ",": "]
["$80,000 - $89,999 ",": "]
["$90,000 - $99,999 ",": "]
["$100,000 - $149,999 ",": "]
["$150,000 and over ",": "]
]
As the title says I have no idea why the list of list is giving me this error. I tried to search up the error but I'm new and unable to understand what they are saying.
You miss , after each list element
theListofSalary = [
[" $0 - $9,999 ",": "],
["$10,000 - $19,999 ",": "],
....
You are missing the commas between items of your main list.
theListofSalary = [
[" $0 - $9,999 ",": "],
["$10,000 - $19,999 ",": "],
["$20,000 - $29,999 ",": "],
["$30,000 - $39,999 ",": "],
["$40,000 - $49,999 ",": "],
["$50,000 - $59,999 ",": "],
["$60,000 - $69,999 ",": "],
["$70,000 - $79,999 ",": "],
["$80,000 - $89,999 ",": "],
["$90,000 - $99,999 ",": "],
["$100,000 - $149,999 ",": "],
["$150,000 and over ",": "]
]
You will notice I added commas to all but the last one, and this should work now :)
You're missing commas (,) after each entry in your list declaration, as the other answers have stated. However, the other answers don't explain why you're seeing the strange error.
What's happening is that Python thinks you're trying to index into the first inner list using the second inner list, which happens to be a tuple data type (or a comma-separated immutable list).
print([""][0]) # this works and prints ""
print([""][0, 0]) # TypeError: list indices must be integers, not tuple
This is important to understand, because the following code causes no problems for the interpreter and could lead to very subtle bugs in a large program:
theListofSalary = [
[" $0 - $9,999 "]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
]
print(theListofSalary)
The above code prints [' ']. Can you see why?
Another example:
theListofSalary = [
[" $0 - $9,999 "]
[0]
[12]
]
print(theListofSalary)
prints ['$']. Again, can you see why this works?
theListofSalary = [
[" $0 - $9,999 "]
[0]
[80]
]
print(theListofSalary)
In the above example, we get IndexError: string index out of range.
theListofSalary = [
[" $0 - $9,999 "]
[0]
["hello world"]
]
print(theListofSalary)
The above example emits TypeError: string indices must be integers.
Hopefully you're beginning to see the pattern here! Long story short, make sure to add commas to your list declarations so the interpreter doesn't mistake your sub-lists as indexing operations on the first sub-list.
Last but not least, the Python style guide suggests snake_cased_variable_names. Titling a list as the_list_of_salaries is needlessly verbose; I recommend calling this list salaries, simply.

If statements operating with a 3x3 array not operating properly

So I have a function that uses if statements and has the parameter of a 3x3 array (in python 3.3.5)
def checkDiagonals (game_board):
match = 0
if game_board[0][0]==game_board[1][1] and game_board[0][1]==game_board[2][2] and game_board[1][1]==game_board[2][2]: #checks if diagonals equal each other
match = game_board[0][0]
if match == " ":
match = "NO WINNER"
match = 0
if game_board[0][2]==game_board[1][1] and game_board[0][2]==game_board[2][0]:
match = game_board[0][0]
if match == " ":
match = "NO WINNER"
return (match)
The problem is,
print (checkDiagonals([["X", " ", " "], [" ", " ", " "], [" ", " ", " "]]))
yields X, when it should yield 0 or NO WINNER. Does anyone want to give me a hint as to why this is so? I just don't see it.
Let's step through the second half of your function.
match = 0
if game_board[0][2]==game_board[1][1] and game_board[0][2]==game_board[2][0]:
match = game_board[0][0]
if match == " ":
match = "NO WINNER"
return (match)
First, match = 0. This unconditionally resets match to 0. That's a red flag, because it overwrites whatever the result of the first half was.
Next, the if statement.
if game_board[0][2]==game_board[1][1] and game_board[0][2]==game_board[2][0]:
If we substitute in the values of those board positions, we get:
if " "==" " and " "==" ":
All of the positions being checked are spaces. The if statement succeeds. That means we proceed to the following assignment.
match = game_board[0][0]
Well the value of position 0,0 is "X". This is equivalent to:
match = "X"
This is why match ends up as "X". The followup check if match == " " fails, so nothing else happens. match remains "X" rather than "NO WINNER".
Walking through the code step by step revealed at least two problems. One is that match is overwritten, so the results of the first diagonal check are lost. Another is that it grabs the letter from the wrong square.

Python creating a 1D and 2D image

The code below was provided to us and it basically prints that image which is shown in the second function:
import sys
# CONSTANTS
MIN_ROW = 0
MAX_ROW = 9
MIN_COLUMN = 0
MAX_COLUMN = 9
WALL = "#"
BUILDING = "b"
BUSH = "u"
PLAYER = "#"
EMPTY = " "
STAIRS = "X"
def display (city):
r = 0
c = 0
print("CITY LEVEL")
for r in range (0, (MAX_ROW+1), 1): #LOOPS1
for c in range (0, (MAX_COLUMN+1), 1):
sys.stdout.write(city[r][c])
print()
print()
def initialize ():
r = 0
c = 0
city = []
for r in range (0, (MAX_ROW+1), 1): #LOOP2
city.append([])#appends an empty list to city
for c in range (0, (MAX_COLUMN+1), 1):
city[r].append(" ")
# 0 1 2 3 4 5 6 7 8 9
city [0] = ["#","#","#","#","#","#","#","#","#","#"]
city [1] = ["#","#"," "," "," "," "," "," ","u","#"]
city [2] = ["#"," "," ","b","b"," "," "," ","X","#"]
city [3] = ["#"," "," ","b","b"," "," "," "," ","#"]
city [4] = ["#"," "," "," "," "," "," "," ","b","#"]
city [5] = ["#","u"," ","u","u","u","u","u","u","#"]
city [6] = ["#","b"," "," "," "," "," "," "," ","#"]
city [7] = ["#"," "," "," "," ","b"," ","b"," ","#"]
city [8] = ["#"," "," "," ","b"," "," "," "," ","#"]
city [9] = ["#","#","#","#","#","#","#","#","#","#"]
return city
# MAIN
def main ():
level = initialize ()
display (level)
main ()
Now I am trying to reproduce this for a 1D picture but for some reason I am running into type errors for the sys.stdout.write() of the first function. It seems to be trying to print the entire list compared to just one character of it. Can anyone help me debug?. Also can someone please tell me what is going on in the loops in the above code labelled LOOPS1 AND LOOPS2
import sys
def display(track):
c=0
for c in range(0,20,1):
sys.stdout.write(track[c])
print()
def initialize():
c=0
track= []
for c in range(0,20,1):
track.append([])
track[c].append(" ")
track[0]= ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
return track
level= initialize()
display(level)
If anything is unclear please let me know and I will fix it asap.
EDIT: CODE FOR MY PROGRAM:
import sys
import random
# CONSTANTS
PLAYER = "#"
EMPTY = " "
#Takes the information from the function initialize() and displays it. Outputs the fitness simulation.
def display (track):
r = 0
c = 0
print("\nTRACK")
for r in range (0, (4), 1):
for c in range (0, (41), 1):
sys.stdout.write(track[r][c])
print()
print()
def speedDisplay(speed):
options=["(w)alk","(j)og","(r)un","(f)ast run"]
for o in range(0,speed,1):
print(options[o],"\n")
def inputs():#ioerror here?
values= set("wWjJrRfFlLsSeE")
while True:
move=input("\nPlease select the speed you would like to travel at from the options listed:")
for m in move:
if m not in values:
print("\nInadmissable entry, Please only use inputs valid in the options above.")
break
else:
break
if move=="w" or move=="W":
usedEnergy=0#turn into random functions later
elif move=="j" or move=="J":
usedEnergy=1
elif move=="r" or move=="R":
usedEnergy=2
elif move=="f" or move=="F":
usedEnergy=5
return usedEnergy
def remainingEnergy(energy,usedEnergy):
energy= energy-usedEnergy
print("\nRemaining Energy:",energy,"\n")
return energy
def amountLeft(energy):
# enter ioexception error here somewhere?
while True:
if energy <0 or energy >20:
print("error")
elif energy>=5:
speed=4
elif energy <5 and energy >=2:
speed=3
elif energy <2 and energy >=1:
speed=2
elif energy <1 and energy >=0:
speed=1
else:
break
return speed
# This function is used to initialize the game track that will later be displayed.
def initialize ():
r = 0
c = 0
track = []
#Creates each row and column. A "for" loop initiates which creates and appends an empty list to the list "track". Then, taking the current row into consideration, the respective number of columns are created via the inner "for loop and a space is appended to the end of the current row. The loop re-initiates and the process is repeated for all 4 required rows. This results in 4 rows and 41 coloumns.
for r in range (0, (4), 1):
#appends an empty list to track
track.append([])
for c in range (0, (41), 1):
#appends a space to the current row
track[r].append(" ")
# the actual rows and columns are created below.
# 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y
track [0] = [" ","0"," ","1"," ","2"," ","3"," ","4"," ","5"," ","6"," ","7"," ","8"," ","9"," ","A"," ","B"," ","C"," ","D"," ","E"," ","F"," ","G"," ","H"," ","I"," ","J"," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "]
track [1] = [" ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," "]
track [2] = ["|","#","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"," ","|"]
track [3] = [" ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," ","-"," "]
return track
def move (sRow, sCol, dRow, dCol, track):
EMPTY= " "
PLAYER= "#"
DIVIDER= "|"
track[sRow][sCol] = EMPTY
track[dRow][dCol] = PLAYER
# MAIN
def main ():
track = initialize ()
display (track)
print("\n(w)alk\n\n(j)og\n\n(r)un\n\n(f)ast run")
usedEnergy=inputs()
energy=20
energy=remainingEnergy(energy,usedEnergy)
while energy<20:
usedEnergy=inputs()
speed= amountLeft(energy)
speedDisplay(speed)
energy=remainingEnergy(energy,usedEnergy)
main ()
Well, this works:
import sys
def display(track):
c=0
for c in range(0,20,1):
sys.stdout.write(track[c])
print()
def initialize():
c=0
track = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"]
return track
level= initialize()
display(level)
Your problem was you had a mismatch in how you're handling track. In initialize you were creating it as a list of lists but in display you were accessing it as if it were just a list of characters. Making both a list of characters was simpler, making both a list of list of chars is more general (allows same function to be used for 1D and 2D case).
What's going on in the first loop?
From display in your first code block:
for r in range (0, (MAX_ROW+1), 1): #LOOPS1
for c in range (0, (MAX_COLUMN+1), 1):
sys.stdout.write(city[r][c])
print()
print()
R is a row index that varies from 0 to MAX_ROW, 0 - 9. C is a column index that varies from 0 to MAX_COLUMN, 0 - 9.
sys.stdout.write(city[r][c]) writes out the current row and column of city (which has been set to a single character) without a newline.
You're code is probably Python 3 due to the print() statements. It would probably help if you mentioned or tagged that.
I'm running Python 2.7 so I'll use the old print syntax so I can test the the code I'm posting. You'll probably have to revert it back (add parens).
I would write this as:
def display (city):
print("CITY LEVEL")
for row in city:
for c in row:
print c,
print
print
In Python 2 a comma at the end of a print suppresses the newline.
What's going on in the second loop?
From initialize in your first code block:
for r in range (0, (MAX_ROW+1), 1):
r will be 0 to MAX_ROW, 0-9
city.append([])#appends an empty list to city
city is a list. This appends an empty list to city.
for c in range (0, (MAX_COLUMN+1), 1):
c will b 0 to MAX_COLUMN, 0-9
city[r].append(" ")
Append a space character to the current row.
I would write this as:
def initialize():
city = [
# 0 1 2 3 4 5 6 7 8 9
["#","#","#","#","#","#","#","#","#","#"], # 0
["#","#"," "," "," "," "," "," ","u","#"], # 1
["#"," "," ","b","b"," "," "," ","X","#"], # 2
["#"," "," ","b","b"," "," "," "," ","#"], # 3
["#"," "," "," "," "," "," "," ","b","#"], # 4
["#","u"," ","u","u","u","u","u","u","#"], # 5
["#","b"," "," "," "," "," "," "," ","#"], # 6
["#"," "," "," "," ","b"," ","b"," ","#"], # 7
["#"," "," "," ","b"," "," "," "," ","#"], # 8
["#","#","#","#","#","#","#","#","#","#"], # 9
]
return city
about city.append([])
In initialize there is a line (in the first for loop):
city.append([])#appends an empty list to city
Before the loop is entered city is:
[]
Right after the first append city is:
[[]]
That is a list that contains one item, an empty list.
If the line were:
city.append(0)
It would be:
[0]
Or:
city.append("Jim")
It would give you:
["Jim"]
But we stick another list inside the list, creating a list of lists.
I hope this helps.

Categories