So I'm attempting to make a Brainfuck interpreter, however in the while loop that I am using to execute the Brainfuck loop, it is breaking out even though only one condition is true.
Example:
+++[>+<-]
Should result in:
[0, 3]
However, when the loop begins at [, it will create a new cell so the structure goes from [3] to [3, 0]. Thus, the current working cell is 0 and the loop is breaking out. However, I have it to only break if it is 0 and the current character is ].
cells = [0] # Array of data cells in use
brainfuck = str(input("Input Brainfuck Code: ")) # Brainfuck code
workingCell = 0 # Data pointer position
count = 0 # Current position in code
def commands(command):
global cells
global workingCell
if command == ">":
workingCell += 1
if workingCell > len(cells) - 1:
cells.append(0)
elif command == "<":
workingCell -= 1
elif command == "+":
cells[workingCell] += 1
elif command == "-":
cells[workingCell] -= 1
elif command == ".":
print(chr(cells[workingCell]))
elif command == ",":
cells[workingCell] = int(input("Input: "))
def looper(count):
global cells
global workingCell
print("START LOOP", count)
count += 1
looper = loopStart = count
while brainfuck[looper] != "]" and cells[workingCell] != 0: # This line is causing trouble
if brainfuck[looper] == "]":
looper = loopStart
commands(brainfuck[looper])
count += 1
looper += 1
return count
while count < len(brainfuck):
if brainfuck[count] == "[":
count = looper(count)
print("END LOOP", count)
else:
commands(brainfuck[count])
count += 1
Thank you in advance.
I have it to only break if it is 0 and the current character is ]
If that's what you want, you have the logic in your while wrong. It should be:
while not (brainfuck[looper] == "]" and cells[workingCell] == 0):
And according to deMorgan's Laws, when you distribute not across and, you invert each of the conditions and change and to or, so it should be:
while brainfuck[looper] != "]" or cells[workingCell] != 0:
If this is confusing, you could just write:
while True:
if brainfuck[looper] == "]" and cells[workingCell] == 0:
break
This mirrors what you said in the description exactly.
Related
I don't know why but my "def" that checks 3 rules of "Game of live" doesn't work correctly. I have 2 lists that contains 0 and some 1 to check the program. 3 points that should give this image but instead it gives this
def upd(mass,screen,WHITE,mass1):
BLACK = (0,0,0)
for i in range(len(mass)-1):
for j in range(len(mass[i])-1):
if mass[i][j] == 0:
if near(mass,i,j) == True:
mass1[i][j]=1
print("case1")
if mass[i][j] == 1:
if (near(mass,i,j)==False):
mass1[i][j]=0
print("case 2")
if (near(mass,i,j)==False):
mass1[i][j]=0
print("case 3")
for i in range(len(mass1)-1):
for j in range(len(mass1[i])-1):
if mass1[i][j] == 1:
p.draw.rect(screen, (WHITE), Rect((j*10,i*10), (10,10)))
else:
p.draw.rect(screen, (BLACK), Rect((j*10,i*10), (10,10)))
mass=mass1
def near(mass,i,j):
counter = 0
if mass[i][j+1]==1:
counter+=1
if mass[i][j-1]==1:
counter+=1
if mass[i+1][j]==1:
counter+=1
if mass[i-1][j]==1:
counter+=1
if mass[i+1][j+1]==1:
counter+=1
if mass[i-1][j+1]==1:
counter+=1
if mass[i+1][j-1]==1:
counter+=1
if mass[i-1][j-1] == 1:
counter+=1
if counter<2 or counter == 0:
return False
if counter > 3:
return False
if counter == 3:
return True
log that repeats every circle
I am not good in python so I think this code is quite scarry:)
I'll be very grateful for any advice
mass = mass1 does not copy the contents of the grid, it just puts a reference to mass1 in mass (actually only in the local variable mass in scope of upd). You must deep copy the grid:
for i in range(len(mass1)):
for j in range(len(mass1[i])):
mass[i][j] == mass1[i][j]
So I have a file "game.txt" which consist of an instruction and a number. The instruction is either "coin," "jump," or "none." "Coin" stores the number following the instruction, "jump" will jump to a new instruction relative to itself and do whatever that instructions says, and "none" will do nothing. However, "jump +2" would continue to the instruction two lines below, and "jump -5" causes the instruction 5 lines above to be executed next.
I want to be able to iterate through the file, write the number on a new file, and count how many "coins" there are at the end. I already have a decent function that gets me somewhat close to this, but I have some bugs that I can't seem to figure out.
ex.)
I have 533 as my total, but only 528 entries in my new file
I would also like to simplify the code if possible (looks redundant in some parts)
game.txt file game.txt file link
def counting_coins(file):
count = 0
game_list = [] # list of all game steps
valid_coins = [] # list of all coin values
try:
coins = open("coins.txt", "x")
except FileExistsError:
coins = open("coins.txt", "w") # if file already exists
with open(file, "r") as cc:
### LOOPS ###
for line in cc:
game_list.append(line[0:-1]) # append each line to list to index and iterate
for i in range(len(game_list)):
current = game_list[i] # keep track of current step
if "coin" == current[0:4]:
count += 1
if game_list[i][5:6] == "+":
valid_coins.append(current[6:] + "\n")
# count += 1
elif game_list[i][5:6] == "-":
valid_coins.append("-" + current[6:] + "\n")
# count += 1
elif "jump" == current[0:4]:
if current[5:6] == "+":
num = int(current[6:])
jump = game_list[i + num]
elif current[5:6] == "-":
num = int(current[6:])
num = -num
jump = game_list[i + num]
if "coin" == jump[0:4]:
count += 1
if jump[5:6] == "+":
valid_coins.append(jump[6:] + "\n")
# count += 1
elif jump[5:6] == "-":
valid_coins.append("-" + jump[6:] + "\n")
# count += 1
elif "jump" == jump[0:4]:
if jump[5:6] == "+":
new_num = int(jump[6:])
new_jump = game_list[(i + num) + new_num]
elif jump[5:6] == "-":
new_num = int(jump[6:])
new_num = -new_num
new_jump = game_list[(i + num) + new_num]
if "coin" == new_jump[0:4]:
count += 1
if new_jump[5:6] == "+":
valid_coins.append(new_jump[6:] + "\n")
# count += 1
elif new_jump[5:6] == "-":
valid_coins.append("-" + new_jump[6:] + "\n")
# count += 1
elif "jump" == new_jump[0:4]:
if new_jump[5:6] == "+":
new_num2 = int(new_jump[6:])
new_jump2 = game_list[(i + num) + new_num + new_num2]
elif new_jump[5:6] == "-":
new_num2 = int(new_jump[6:])
new_num2 = -new_num2
new_jump2 = game_list[(i + num) + new_num + new_num2]
if "coin" == new_jump2[0:4]:
count += 1
if new_jump2[5:6] == "+":
valid_coins.append(new_jump2[6:] + "\n")
# count += 1
elif new_jump2[5:6] == "-":
valid_coins.append("-" + new_jump2[6:] + "\n")
# count += 1
elif "none" == current[0:4]:
continue
for i in range(len(valid_coins)):
if valid_coins[i] == valid_coins[-1]: # if last entry
coins.write(valid_coins[i][:-1]) # removes preceding newline
else:
coins.write(valid_coins[i])
coins.close()
return coins, count
file, count = counting_coins("game.txt")
print(f"Total coins collected: {count}")
Don't use all those nested if statements for jumping. Just reset the current index of the main loop to the element that you're jumping to.
You'll need to use a while loop instead of looping over range() so you can reset the index.
Instead of all that slicing, use split() to split each line into a command and argument.
i = 0
while i < len(game_list):
current = game_list[i].split()
if current[0] == "coin":
count += 1
valid_coins.append(current[1])
elif current[0] == "jump"
i += int(current[1])
elif current[0] = "none":
pass
else:
print(f"invalid line {game_list[i]}")
with open("coins.txt", "w") as coins:
coins.write("\n".join(valid_coins))
There's no need for the try/except. Opening in w mode will create the file if it doesn't already exist, you don't need x for that.
My Problem is on line 25 when it says
if conformation == 1:
for i in range(l, len(lines[k]), 1):
if lines[k][i].isdigit() or lines[k][i].istitle():
f += lines[k][i]
if f in var:
print(var[f])
What my issue is is that the "f" string isn't being added to and its value stays as "". For context, I'm trying to make my own sort of mini programming language, and I'm trying to make prints read for variables. Every time it loops to set f to the variable name, nothing happens. The only way I get remotely close to finding the variable name is by doing "print(lines[k][i])" before the "if lines[k][i]" condition.
Note: I was using a debugger, and I'm not sure if the "if f in var" condition is even being checked.
Python code that reads my custom programming language:
⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
code = open("HelloWorld.sabo", 'r')
lines = code.readlines()
var = {}
for k in range(0, len(lines), 1):
conformation = 0
temp = ""
temp2 = ""
if lines[k][0:5] == "print":
r = 0
l = 0
p = False
f = ""
for i in lines[k]:
r += 1
if not p:
l += 1
if i == "(":
p = True
conformation += 1
if i == "\"" and conformation == 1:
conformation += 1
if conformation == 2:
break
if conformation == 1:
for i in range(l, len(lines[k]), 1):
if lines[k][i].isdigit() or lines[k][i].istitle():
f += lines[k][i]
if f in var:
print(var[f])
if conformation == 2:
for i in range(r, len(lines[k]), 1):
if not lines[k][i] == "\"":
f += lines[k][i]
else:
break
print(f)
elif lines[k][0:4] == "var ":
for i in range(4, len(lines[k]), 1):
if not lines[k][i] == " ":
temp += lines[k][i]
else: break
for i in range(4, len(lines[k])):
if lines[k][i] == "=":
conformation = 1
elif conformation == 1:
if not lines[k][i] == " ":
temp2 += lines[k][i]
elif not temp2 == "":
break
var[temp] = temp2.strip()
Code that is being read by the above script:
⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
var val = hello
print(val)
So, I was being a bit dumb with this, but I found out that if I just account for Uppercase and Lowercase characters, then it will work.
if lines[k][i].islower() or lines[k][i].isdigit() or lines[k][i].isnumeric() or lines[k][i].istitle():
f += lines[k][i]
I might have gone overboard with the security though I'm just not sure about the difference isdigit and isnumeric.
I'm making an isWin function that checks if there is a character that appears 5 consecutive times (either horizontally, vertically or diagonally).
I've tried using this code:
#VERTICAL WIN
count = 0
for row in range(1,grid_height):
print(row)
for col in range(1,grid_width):
print(col)
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
#HORIZONAL WIN
count=0
for col in range(0,grid_width):
for row in range(0,grid_height):
if grid[row][col-2] == p_char:
count += 1
if count == 5:
return True
else:
count = 0
continue
And this is where i place it in my main program:
def play():
grid,grid_height,grid_width,p1_name,p1_char,p2_name,p2_char=getGameSettings()
displayGrid(grid,grid_height,grid_width)
print('WELCOME TO THE GAME!')
playerA = Player(p1_name, PLAYING)
playerB = Player(p2_name, WAITING)
grid=[]
for row in range(grid_height): # FOR ROW
z =[]
for col in range(grid_width): # FOR COLUMN
z.append(" ")
grid.append(z)
numColFull = 0
turn=0
while turn < grid_height*grid_width:
player = playerA
if turn % 2 == 0 : #IF TURN IS AN ODD NUMBER, THEN IT IS player 1's turn, IF TURN IS EVEN, THEN IT IS player 2's turn
p_char= p1_char
player = playerA
playerA.setState(PLAYING)
playerB.setState(WAITING)
else :
p_char= p2_char
player = playerB
playerB.setState(PLAYING)
playerA.setState(WAITING)
print(".................................................. ")
print("User to play : ", player.playerInfo() , " SEQ : ", str(turn)) # TO COUNT THE TOTAL NUMBER OF MOVES
print(".................................................. ")
if numColFull == grid_width: #THE isDRAW function but embedded into the main function
# IF the numColFull is equal to gridwidth, it means that all of the columns has been occupied, meaning
#that every space has already been occupied, thus, game is over.
print('........All spaces had been occupied...........')
print('................THE GAME IS DRAW...............')
print('.................GAME OVER.....................')
break
else:
while True:
try:
move=int(input('Enter your move: '))
except ValueError:
print('Please enter a valid input.')
if move < 1 or move > grid_width:
print('Please enter a valid input.')
continue
break
updateGrid(grid,grid_height-1,grid_width,move,p_char)
while True:
if grid[0][move-2] == p_char: #IF THE TOP ROW OF A COLUMN HAS A PIECE IN IT, IT MEANS ITS ALREADY FULL
displayGrid(grid,grid_height, grid_width)
print('Column is full. Please choose another column for the next move.')
numColFull += 1
break
elif isWin == True: #IF THE IF CONDITION DIDNT HOLD TRUE, THEN THE FUNCTION CONTINUES AS USUAL
print(player, 'WINS!!!')
('.................GAME OVER.....................')
else:
displayGrid(grid,grid_height, grid_width)
break #GOES BACK TO THE THE WHILE CONDITION
turn += 1 #INCREMENTS 1 TO TURN SO IT WILL SWITCH BETWEEN BEING ODD AND EVEN
And this is my grid:
def displayGrid(grid,grid_height,grid_width):
for row in range(1,grid_height):
#print(row) #for checking
for col in range(grid_width):
print("|", end="")
print(str(grid[row-1][col-1]),end = "")
print("|")
print(" "+" ".join([str(i) for i in range(1, grid_width+1)]))
return grid
def updateGrid(grid,grid_height,grid_width,move,p_char):
for i in range(1,grid_height+1):
print(i)
#print(i) #ROW COUNTING STARTS FROM 1
if grid[grid_height-i][move-2] == " ":
grid[grid_height-i][move-2]= p_char #REPLACES THE " " TO THE CURRENT PLAYER'S CHARACTER (p_char)
else:
continue
break
return grid
I guess you are writing Five In a Row? But anyway, this code should work:
def isWin():
# Horizontal
for i in range(grid_height):
for j in range(grid_width - 4):
if set(grid[i][j:j+5]) == {p_char}:
return True
# Vertical
for i in range(grid_height - 4):
for j in range(grid_width):
if { grid[i+k][j] for k in range(5) } == {p_char}:
return True
# Diagonal
for i in range(grid_height - 4):
for j in range(grid_width - 4):
if { grid[i+k][j+k] for k in range(5) } == {p_char}:
return True
return False
# Simplified
def isWin():
return any(set(grid[i][j:j+5]) == {p_char} for i in range(grid_height) for j in range(grid_width - 4)) or \
any({ grid[i+k][j] for k in range(5) } == {p_char} for i in range(grid_height - 4) for j in range(grid_width)) or \
any({ grid[j+k][i+k] for k in range(5) } == {p_char} for i in range(grid_width - 4) for j in range(grid_width - 4))
Since set cannot have duplicates, using expressions like { grid[j+k][i+k] for k in range(5) } will put 5 consecutive pieces into a set. If there are 5 consecutive p_chars, then the set will become {p_char}.
I need to check if a string is a valid number or not.
Here are some examples of valid:
1234
-1234
12.4
0.6
-0.6
-1234567890.123456789
Non-valid:
+123
123.
.6
00.6
12-.6335
If the first digit is a 0, a decimal point "." must come after it.
I have tried the following code but it says "time limit exceeded". I'm not sure what that means.
def valid_float(number_string):
counter = 0
if number_string[0].isdigit() or number_string[0] == "-" or number_string[0] == "0":
while number_string[0] == "-":
if number_string[1].isdigit():
counter += 1
else:
counter = 0
while number_string[0].isdigit():
if number_string[1] == "." and number_string[2].isdigit():
counter += 1
else:
counter = 0
while number_string[0] == "0":
if number_string[1] == ".":
counter += 1
else:
counter = 0
if counter == 3:
return True
else:
return False
else:
counter = 0
The error you get means that the program keeps going for a long time because it is 'stuck' somewhere. Most of the time its because of a bad recursion function or, in this case, a while loop that will loop forever.
Your while loops will loop forever because you don't change the thing it checks as condition: if the condition is true in the beginning it will be true all the time so the program will never quit the while loop.
I wanted to correct your code but I can't figure out what you where trying so here is some code that will hopefully help you out:
for i in range(0,len(number_string)):
if i == 0 and number_string[0] == "." :
return false
if i != 0 and number_string[0] == "." :
continue
if i == 0 and number_string[0] == "-" :
continue
if i == 0 and number_string[0] == "0" and len(number_string[0])>1:
if number_string[1] != "." :
return false
if number_string[i].isdigit():
continue
return false