Lists in classes losing data - python

I'm trying to parsing text from a file, the first character in a line will be used to decide of what type the remaining text should be.
'?' - Question, '#' - Description, '!' - Answers, and the next number will determine what is the correct answer.
I want to have an object that stores the respective data, and a class that holds references to those objects (list of objects). The amount of answers can vary, so I tried to use a list for that.
The problem is that the returned "answers" list is blank.
Where did I go wrong?
class Question:
def __init__(self, ques, desc, n_ans, corr, ans):
self.ques = ques
self.desc = desc
self.n_ans = n_ans
self.corr = corr
self.ans = ans
print(self.ans)
def get(self):
print(self.ans)
return [self.ques, self.desc, self.n_ans, self.corr, self.ans]
class Question_handler:
arr_ans = []
array = []
firstTime = True
def __init__(self):
self.num_ans = 0
self.cor_ans = 0
self.ques = None
self.desc = None
def question(self, ques): # if it isn't the first time reaching a line starts with '?'
if self.firstTime == True: # the data is made into an instance of Question
pass
else:
self.array.append(Question(self.ques, self.desc, self.num_ans, self.cor_ans, self.arr_ans)) # List of objects
self.ques = None # Reset everything
self.desc = None
self.num_ans = 0
self.cor_ans = 0
self.arr_ans.clear()
self.ques = ques
self.firstTime = False
def description(self, desc):
if self.desc == None:
self.desc = desc
else:
self.desc = self.desc + '\n' + desc
def answer(self, ans):
self.arr_ans.append(ans) # Append answers (line starts with '!') to list
self.num_ans = len(self.arr_ans)
def correct(self, num):
if num >= 1 and num <= len(self.arr_ans):
self.cor_ans = num
else:
self.cor_ans = 0
def end(self): # Reach EOF
if self.ques == None:
pass
else:
self.question(None) # To push the remaining data
def get(self, Nques): # Get info of Question
if Nques <= len(self.array) and Nques >= 1:
return self.array[Nques - 1].get()
QQ = Question_handler()
Qfile = open('C:/Users/Admin/Desktop/test/test.txt','r')
Qdata = Qfile.readlines()
for line in Qdata:
Qline = line[1:-1]
if line[0] == '?':
QQ.question(Qline)
continue
if line[0] == '#':
QQ.description(Qline)
continue
if line[0] == '!':
QQ.answer(Qline)
continue
if line[0].isnumeric():
QQ.correct(int(line[0]))
continue
else:
QQ.end() # EOF
print(QQ.get(1))
print(QQ.get(2))
print(QQ.get(3))
TXT file
?Cau 1
#Test so 1
!abc
!def
!ghj
!ikl
3
?Cau 2
#Test so 2
!100
!1000
!10000
2
?Question 3
!A
!B
!C
!D
!E
5
Output
['abc', 'def', 'ghj', 'ikl']
['100', '1000', '10000']
['A', 'B', 'C', 'D', 'E']
[]
['Cau 1', 'Test so 1', 4, 3, []]
[]
['Cau 2', 'Test so 2', 3, 2, []]
[]
['Question 3', None, 5, 5, []]

Related

dictionary Is extracting the wrong values in python

I am having issues with python dictionary, currently, I am trying to implement a binary search algorithm without using extensions, and I am stuck, the function could only extract the last middle items, it cannot extract the first and last items. Here are my codes:
object
class Customer:
def __init__(self,packageName,customerName,numberOfPax,packagePaxPerCost):
self.__packageName = packageName
self.__customerName = customerName
self.__numberOfPax = numberOfPax
self.__packagePaxPerCost = packagePaxPerCost
def get_packageName(self):
return self.__packageName
def get_customerName(self):
return self.__customerName
def get_numberOfPax(self):
return self.__numberOfPax
def get_packagePaxPerCost(self):
return self.__packagePaxPerCost
def set_packageName(self,packageName):
self.__packageName = packageName
def set_customerName(self,customerName):
self.__customerName = customerName
def set_numberOfPax(self,numberOfPax):
self.__numberOfPax = numberOfPax
def set_packagePaxPerCost(self,packagePaxPerCost):
self.__packagePaxPerCost = packagePaxPerCost
dictionary items
Records_dict = {}
############################ Dummy Data #############################
Records1 = Customer('normal suite 2', 'Bobby', '1', '100')
Records_dict[Records1.get_customerName()] = Records1
Records2 = Customer('normal suite 4', 'Tommy', '30', '400')
Records_dict[Records2.get_customerName()] = Records2
Records3 = Customer('normal suite 1', 'Johny', '10','500')
Records_dict[Records3.get_customerName()] = Records3
Records4 = Customer('normal suite 3', 'Jimmy', '20', '300')
Records_dict[Records4.get_customerName()] = Records4
Records5 = Customer('normal suite 4', 'Jim', '90','900')
Records_dict[Records5.get_customerName()] = Records5
#####################################################################
selection sort algorithm
def selectionSort(entries):
list2 = []
sortedDict = {}
for eachitem in entries.values():
list2.append(eachitem.get_customerName())
n = len(list2)
for eachitem2 in range(n-1):
smallestNumber = eachitem2
for j in range(eachitem2+1, n):
if entries[list2[j]].get_packageName().lower() < entries[list2[smallestNumber]].get_packageName().lower():
smallestNumber = j
if smallestNumber != eachitem2:
tmp = entries[list2[eachitem2]]
entries[list2[eachitem2]] = entries[list2[smallestNumber]]
entries[list2[smallestNumber]] = tmp
return entries
binary search algorithm
def binarySearch(target, entries2):
entries = selectionSort(entries2)
list = []
for eachItem in entries.values():
list.append(eachItem.get_customerName())
print(list)
low = 0
list2 = []
high = len(list)-1
print(entries[list[0]].get_packageName())
while low <= high:
mid = (high+low)//2
print(entries[list[0]].get_packageName())
print(entries2[list[mid]].get_packageName())
if entries2[list[mid]].get_packageName().lower() == target.lower():
customerName = entries[list[mid]].get_customerName()
packageName = entries[list[mid]].get_packageName()
numberOfPax = entries[list[mid]].get_numberOfPax()
packagePaxPerCost = entries[list[mid]].get_packagePaxPerCost()
list2.append([packageName, customerName, numberOfPax, packagePaxPerCost])
return list2
elif target.lower() < entries[list[mid]].get_packageName().lower():
high = mid - 1
else:
low = mid + 1
list2 = []
if list2 == []:
print('blank')
return list2
test = binarySearch('normal suite 2',Records_dict)
print(test)

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

Python: Recursion problems

I am trying to make a sudoku solver that solves boards very quickly. At the moment my solver works on easy boards but never terminates on harder boards. I believe it has something to do with my recursion because easy boards do not require recursion and hard boards do. Any help is appreciated.
import sys
def rowno(i):
return i // 9
def colno(i):
return i % 9
def boxno(i):
return (i // 9 // 3 )*3 + (i // 3) % 3
def isNeighbor(i, j):
if rowno(i) == rowno(j) or colno(i) == colno(j) or boxno(i) == boxno(j):
return True
else:
return False
def getFileName():
if sys.platform == "win32":
filename = input("Filename? ")
else:
filename = sys.argv[-1]
return filename
solutionlist = []
class Board(object):
def __init__(self, puzzle):
self.puzzle = puzzle
self.board = [Cell(int(value), idx) for idx, value in enumerate(puzzle)]
self.change = False
def printAll(self):
print [cell.candidates for cell in self.board]
#return str(" ")
def update(self):
self.change = False
l = [cell for cell in self.board if len(cell.candidates) == 1]
for i in l:
for j in xrange(81):
if isNeighbor(i.dex, j) and i.dex != j:
old = self.board[j].candidates
self.board[j].delCandidate(i.value)
if len(old) != len(self.board[j].candidates):
self.change = True
def toString(self):
str1 = ''.join(str(e.value) for e in self.board)
return str1
def solved(self):
for cell in self.board:
if len(cell.candidates) != 1:
return False
return True
def solve(self):
self.change = True
while self.change == True:
self.update()
if self.solved():
solutionlist.append(self.board)
return
l = [cell for cell in self.board if len(cell.candidates) > 1]
for i in l:
for j in i.candidates:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()
return
def __repr__(self):
l = [cell.value for cell in self.board]
return str(l)
class Cell(object):
def __init__(self, value, dex):
self.value = value
self.dex = dex
if value == 0:
self.candidates = [1,2,3,4,5,6,7,8,9]
else:
self.candidates = [int(value)]
def __str__(self):
return str(self.value)
def delCandidate(self, value):
# deletes value from candidate list
#return self.candidate.remove(value);
self.candidates = [x for x in self.candidates if x != value]
if len(self.candidates) == 1:
self.value = self.candidates[0]
easy = "700583006006001405052006083300200958500078060648010300060802500003150072215600030"
twosol = "000805200800000401705040009000100702040000000006430000030900000010006080000000000"
hard = "040090008000000070060000120030020000005839060080600700050170600000043000003000200"
#easy solution: 794583216836721495152496783371264958529378164648915327967832541483159672215647839
b = Board(hard)
print b
b.solve()
print "end of the line"
for i in solutionlist:
print [cell.value for cell in i]
print "\n"
One major issue is the line for i in l: in the solve method. Since you're recursing, you only need to fill in one cell - the recursion will take care of the rest. So instead of for i in l:, just recurse on the one cell that is the best candidate (curCell):
l = [cell for cell in self.board if len(cell.candidates) > 1]
if len(l) > 0:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()

Linebreak not working - Python

Somehow the linebreaks are not working as they should.
This is what I get:
Expected:
O meu u2 2 post
http://www.yahoo.com
1 Gosto, 0 Nao gosto
<BLANKLINE>
O meu u2 post
http://www.altavista.com
1 Gosto, 0 Nao gosto
Got:
'O meu u2 2 post\nhttp://www.yahoo.com\n1 Gosto, 0 Nao Gosto\n\nO meu u2\nhttp://www.yahoo.com\n1 Gosto, 0 Nao Gosto'
This is the code used in the function.
The important parts should be the str and showRecentComments functions
class Comments():
def __init__(self, u=None, text='', link=None):
self.u = u
self.text = text
self.link = link
self.topo = None
self.fim = None
def __str__(self):
actual = self.topo
s = ''
if actual == None:
return None
while actual != None:
if actual.seg == None:
s += str(actual)
actual = actual.seg
else:
s += str(actual) + '\n' + '\n'
actual = actual.seg
return s
def add(self,comment):
if self.topo == None:
self.topo = comment
self.fim = comment
else:
comment.seg = self.topo
self.topo.ant = comment
self.topo = comment
def remove(self,comment):
actual = self.topo
if (self.topo == self.fim) and (self.topo == comment):
self.topo = None
self.fim = None
while actual!=None:
if actual == comment:
if self.topo==comment:
actual.seg.ant = None
self.topo = actual.seg
elif self.fim==comment:
actual.ant.seg = None
self.fim = actual.ant
else:
actual.seg.ant = actual.ant
actual.ant.seg = actual.seg
break
else:
actual = actual.seg
def countLike(self):
count = 0
actual = self.topo
while actual != None:
if len(actual.likeList) >= 1:
count += 1
actual = actual.seg
else:
actual = actual.seg
return count
def showRecentComments(self,n):
count = 1
actual = self.topo
sC = ''
if actual == None:
return None
while actual != None:
if count < n:
sC += str(actual) + '\n' + '\n'
count += 1
actual = actual.seg
elif count == n:
sC += str(actual)
count += 1
actual = actual.seg
elif count > n:
break
return sC
Regards, Nelson Gregório
It looks like you're looking at the representation of the string, which will show you the newline characters as \n. If you print or write to e.g. stdout (sys.stdout.write(s)) the string instead, the newlines will be expanded.

Parsing Data from live website in Python Enumerate problem!

The following script is supposed to fetch a specific line number and parse it from a live website. It works for like 30 loops but then it seems like enumerate(f) stops working correctly... the "i" in the for loop seems to stop at line 130 instead of like 200 something. Could this be due to the website I'm trying to fetch data from or something else? Thanks!!
import sgmllib
class MyParser(sgmllib.SGMLParser):
"A simple parser class."
def parse(self, s):
"Parse the given string 's'."
self.feed(s)
self.close()
def __init__(self, verbose=0):
"Initialise an object, passing 'verbose' to the superclass."
sgmllib.SGMLParser.__init__(self, verbose)
self.divs = []
self.descriptions = []
self.inside_div_element = 0
def start_div(self, attributes):
"Process a hyperlink and its 'attributes'."
for name, value in attributes:
if name == "id":
self.divs.append(value)
self.inside_div_element = 1
def end_div(self):
"Record the end of a hyperlink."
self.inside_div_element = 0
def handle_data(self, data):
"Handle the textual 'data'."
if self.inside_div_element:
self.descriptions.append(data)
def get_div(self):
"Return the list of hyperlinks."
return self.divs
def get_descriptions(self, check):
"Return a list of descriptions."
if check == 1:
self.descriptions.pop(0)
return self.descriptions
def rm_descriptions(self):
"Remove all descriptions."
self.descriptions.pop()
import urllib
import linecache
import sgmllib
tempLine = ""
tempStr = " "
tempStr2 = ""
myparser = MyParser()
count = 0
user = ['']
oldUser = ['none']
oldoldUser = [' ']
array = [" ", 0]
index = 0
found = 0
k = 0
j = 0
posIndex = 0
a = 0
firstCheck = 0
fCheck = 0
while a < 1000:
print a
f = urllib.urlopen("SITE")
a = a+1
for i, line in enumerate(f):
if i == 187:
print i
tempLine = line
print line
myparser.parse(line)
if fCheck == 1:
result = oldUser[0] is oldUser[1]
u1 = oldUser[0]
u2 = oldUser[1]
tempStr = oldUser[1]
if u1 == u2:
result = 1
else:
result = user is oldUser
fCheck = 1
user = myparser.get_descriptions(firstCheck)
tempStr = user[0]
firstCheck = 1
if result:
array[index+1] = array[index+1] +0
else:
j = 0
for z in array:
k = j+2
tempStr2 = user[0]
if k < len(array) and tempStr2 == array[k]:
array[j+3] = array[j+3] + 1
index = j+2
found = 1
break
j = j+1
if found == 0:
array.append(tempStr)
array.append(0)
oldUser = user
found = 0
print array
elif i > 200:
print "HERE"
break
print array
f.close()
Perhaps the number of lines on that web page are fewer than you think? What does this give you?:
print max(i for i, _ in enumerate(urllib.urlopen("SITE")))
Aside: Your indentation is stuffed after the while a < 1000: line. Excessive empty lines and one-letter names don't assist the understanding of your code.
enumerate is not broken. Instead of such speculation, inspect your data. Suggestion: replace
for i, line in enumerate(f):
by
lines = list(f)
print "=== a=%d linecount=%d === % (a, len(lines))
for i, line in enumerate(lines):
print " a=%d i=%d line=%r" % (a, i, line)
Examine the output carefully.

Categories