Variable not defined even though it exists - python

This is a simple code I wrote for the flanker task:
import random
congruent = open('congruent.txt', 'r')
incongruent = open('incongruent.txt', 'r')
def createList(file):
lst = []
for row in file:
lst.append(row.strip('\n'))
return lst
file.close()
lstCongruent = createList(congruent)
lstIncongruent = createList(incongruent)
nr_trials = 20
def middleString(txt):
middle = txt[(len(txt)-1)//2]
return middle
def checkCongruency(item):
if item in lstCongruent:
correctCongruentAnswers = 0
correctCongruentAnswers += 1
return correctCongruentAnswers
elif item in lstIncongruent:
correctIncongruentAnswers = 0
correctIncongruentAnswers += 1
return correctIncongruentAnswers
for i in range(nr_trials):
rndItem = random.choice(lstCongruent + lstIncongruent)
print(rndItem)
answer = input('Please write your answer: ')
if answer == 'STOP':
exit()
while answer != 'F' and answer != 'J':
print('\33[91m Please type only F or J \33[0m')
break
if middleString(rndItem) == '<' and answer == 'F':
print('Correct answer!')
checkCongruency(rndItem)
elif middleString(rndItem) == '>' and answer == 'J':
print('Correct answer!')
checkCongruency(rndItem)
else:
print('Incorrect answer')
print('Correct congruent answers: ', correctCongruentAnswers)
print('Correct incongruent answers: ', correctIncongruentAnswers)
But when I run it, I get:
File "main.py", line 68, in <module>
print('Correct congruent answers: ', correctCongruentAnswers)
NameError: name 'correctCongruentAnswers' is not defined
is there any way to solve this without completely changing the code? I've tried different things, like defining the functions inside the for loop or some other stuff, but it won't work.

Since variable inside functions can only be use within the function, you can declare them as being global variables, albeit this is not good practice.
def checkCongruency(item):
global correctCongruentAnswers #here
global correctIncongruentAnswers #and here
if item in lstCongruent:
correctCongruentAnswers = 0
correctCongruentAnswers += 1
return correctCongruentAnswers
elif item in lstIncongruent:
correctIncongruentAnswers = 0
correctIncongruentAnswers += 1
return correctIncongruentAnswers

Related

Trying to Iterate Through File and Having Issues

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.

Why is the "f" string not changing

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.

How to extract data from a txt.readlines()?

I have a code that seems to have a slight issue it reads the file... But the issue is it can not identify the words/letters this is what i mean extract('test.txt',('A','E','I','O','U')) the test.txt is a txt file and the ('A','E','I','O','U') is the words i want to find.
my code:
def extract(file,find=()):
with open(str(file),'r') as file:
find = list(find)
read_file = file.readlines()
num1 = 0
num = num1-1
for vals in find:
num1 += 1
pass
for finds in read_file:
linef = str(finds)
main_obj = find[num]
if main_obj in linef:
print("Yay")
elif linef != main_obj:
print("NO")
else:
print("???")
pass
extract('test.txt',('A','E','I','O','U'))
What my output is:
NO
NO
NO
NO
Yay
This is the expected output:
Yay
Yay
Yay
Yay
Yay
inside test.txt:
A
E
I
O
U
I'll just leave this here. If the end result is to compare each variable inside of find to each line in file then this should do the job:
def extract(file, find=()):
with open(file) as F:
contents = F.readlines()
for line in contents:
if any([i in line for i in find]):
print("Yay")
else:
print("NO")
extract("test.txt", ('A','E','I','O','U'))
You just need to update your logic and remove this code. because it will always return -1 index on every increment.
num1 = 0
num = num1-1
for vals in find:
num1 += 1
pass
Just use one variable and increment it accordingly.
def extract(file, find=()):
num = 0
with open(str(file), 'r') as file:
find = list(find)
print(find)
read_file = file.read().splitlines()
print(read_file)
for finds in read_file:
linef = str(finds)
main_obj = find[num]
num += 1
if main_obj in linef:
print("Yay")
elif linef != main_obj:
print("NO")
else:
print("???")
pass
In the code:
for finds in read_file:
linef = str(finds)
main_obj = find[num]
if main_obj in linef:
print("Yay")
elif linef != main_obj:
print("NO")
you never increment num and hence are essentially always comparing find[-1] with main_obj. I guess you have to increment num if there is a match or whatever your requirement is.
if main_obj in linef:
num += 1
print("Yay")
Either way, this would be the most down-to-earth correct way to do what you are required to:
for temp in find:
not_found = True
for finds in read_files:
if temp in finds:
not_found = False
print("Yay")
break
elif temp != finds:
not_found = True # elif is not needed TBH but just adding for clarity
if not_found:
print("NO")

update value in python dictionary by adding a number

I want to make a program that adds a name in the dictionary if it doesn't exist already and count the times it is given as input. My code works, however, it doesn't add 1 when it iterates.
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
for name in namelist:
if word == name:
namelist[word] += 1
# else wasn't properly indented earlier
else:
namelist[word] = 1
print(namen())
print(namelist)
You can use the dict.get method instead to provide a default value to a new entry to the dict:
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
for name in namelist:
if word == name:
namelist[word] = namelist.get(word, 0) + 1
Your check is incorrect, you need if rather than for to see if the key exists, then you can remove the inner if statement
if name in namelist:
namelist[word] += 1
else:
namelist[word] = 1
No one said anything about the has_key method of dictionaries, which is in my opinion the standard way to to this:
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
if namelist.has_key(word):
namelist[word] += 1
else:
namelist[word] = 1
print(namen())
print(namelist)
try this
namelist = {}
def namen():
while True:
word = input('Vul een naam in: ')
if word == '':
break
else:
try:
namelist[word] += 1
except:
namelist[word] = 1
print(namen())
print(namelist)

why cannot I keep all varibles in the list when while loop is running

while not endgame:
cardsOnTable = OnTable()
faceUp1 = player1.dequeue()
cardsOnTable.place('player1',faceUp1,False)
faceUp2 = player2.dequeue()
cardsOnTable.place('player2',faceUp2,False)
print(str(cardsOnTable))
size1 = player1.size()
size2 = player2.size()
print('Player1 : '+str(size1),'Player2 : '+str(size2))
result = compareCard(faceUp1,faceUp2)
elif result == 0:
print('WAR STARTS!!!')
i = 0
player1war = [] #a list for placing player1's card in war(cards on table)
player2war = [] #a list for placing player2's card in war(cards on table)
while i < nbWarCards:
faceDown1 = player1.dequeue()
player1war.append(faceDown1)
faceDown2 = player2.dequeue()
player2war.append(faceDown2)
i += 1
for card in player1war:
cardsOnTable.place('player1',card,True)
player1war.clear()
for card in player2war:
cardsOnTable.place('player2',card,True)
player2war.clear()
if player1.size() == 0 or player2.size() == 0:
endgame = True
my problem happens when I tried to print(str(cardOnTable)) when the first time this while loop runs, it will give me [AS | AH], that's what I want. However, when this while loop runs second time, it is supposed to print [A3 XX XX XX AS | AH XX XX XX A5],it only prints [A3 | A5].
this is my class OnTable():
class OnTable:
def __init__(self):
self.__cards = []
self.__faceUp = []
def place(self,player,card,hidden):
if player == 'player2':
self.__cards.append(card)
if hidden == False:
self.__faceUp.append(False)
elif hidden == True:
self.__faceUp.append(True)
elif player == 'player1':
self.__cards.insert(0,card)
if hidden == False:
self.__faceUp.insert(0,False)
elif hidden == True:
self.__faceUp.insert(0,True)
#return self.__cards
def cleanTable(self):
self.__cards.clear()
self.__faceUp.clear()
def __str__(self):
for i in range(len(self.__faceUp)):
if self.__faceUp[i] == True:
self.__cards[i] = 'XX'
list1 = '['
for item in self.__cards:
list1 += (str(item)+' ')
list1 = re.sub(' ', ' ', list1.strip())
half = int(len(list1)//2)
list1 = list1[:half] + ' |' + list1[half:]
return list1 + ']'
I tried to track my code, and I found self.__cards have all variables before second time the player1.dequeue(), then it loses all the previous variables.
Could someone please tell how to fix this problem? Thank you

Categories