Program error in text prediction algorithm in Python 2.7 - python

I came across the following code from this question :
from collections import defaultdict
import random
class Markov:
memory = defaultdict(list)
separator = ' '
def learn(self, txt):
for part in self.breakText(txt):
key = part[0]
value = part[1]
self.memory[key].append(value)
def ask(self, seed):
ret = []
if not seed:
seed = self.getInitial()
while True:
link = self.step(seed)
if link is None:
break
ret.append(link[0])
seed = link[1]
return self.separator.join(ret)
def breakText(self, txt):
#our very own (ε,ε)
prev = self.getInitial()
for word in txt.split(self.separator):
yield prev, word
prev = (prev[1], word)
#end-of-sentence, prev->ε
yield (prev, '')
def step(self, state):
choice = random.choice(self.memory[state] or [''])
if not choice:
return None
nextState = (state[1], choice)
return choice, nextState
def getInitial(self):
return ('', '')
When i ran the code on my system the example didn't work.
When i ran the bob.ask() line i got an error saying ask() required 2 parameters whereas it got just one. Also when i ran the bob.ask("Mary had") part i got ' ' as the output.
P.S I ran the the code exactly as told in the answer.
Could anyone help? Thanks!

I think you're right. It doesn't work because ask expects an argument (seed), as defined by
def ask(self, seed):
This line
if not seed:
seed = self.getInitial()
suggests that you can fix the issue by setting a default argument for seed. Try this:
def ask(self, seed=False):
which works for me.

Related

I am having troubles getting the list instead of an bound method

import random
from random import randint as rand
upperCase = chr(rand(65,66))
lowerCase = chr(rand(97,122))
class PasswordLetters:
def __init__(self):
pass
def generateCapitalCaseLetter(self):
uppCase = chr(rand(65,91))
return uppCase
def generateLowerCaseLetter(self):
lowCase = chr(rand(97,122))
return lowCase
def generateSpecialLetter(self):
specLet = random.choice(specialCharacters)
return specLet
def generateNumber(self):
num = rand(1,99)
class PasswordGenerator:
def __init__(self,uppCase,lowCase,specLet,num):
self.uppCaseList = []
lowCaseList = []
specLet = []
numList = []
self.passLetter = PasswordLetters()
for i in range(0,uppCase):
self.uppCaseList.append(self.passLetter.generateCapitalCaseLetter)
password = PasswordGenerator(1,1,1,1)
password.uppCaseList
So The Problem I am facing is when I try to get uppCaseList back from my password object it comes back to me as an method in a list instead of a letter in a list. I think the problem is in my PasswordLetters class but I can't figure it out.
The only thing I want is for
password.uppCaseList
to return a list with letters
Since it's a function you are calling, it would need to include the ( open and close ) parentheses. You may refer here for explanation.
for i in range(0,uppCase):
self.uppCaseList.append(self.passLetter.generateCapitalCaseLetter())

assert menu.__str__() == "" AssertionError

I get assertion error when i try to assert "" (empty string) into str function. Could anyone enlighten me as of why that happens. Totally clueless here. I know the str function needs to return a string but as far as i know it is returning a string when i run:
The error comes when i run:
menu = Menu()
assert menu.str() == ""
here is my code:
class Node:
def __init__(self):
self.counter = counter
my_list = []
self.my_list = my_list
def __str__(self):
for element in self.a_list:
if element:
return "\n".join(f"{counter}. {element}" for counter,
element in enumerate(self.my_list, 1))
print()
As the declaration is def __str__(self): you need to call it like
assert menu.__str__() == ""
Or using str method
assert str(menu) == ""
Also you have a for loop, that includes another loop on the same a_list. A good implementation is
# with classic for loop syntax
def __str__(self):
result = ""
for counter, element in enumerate(self.a_list, 1):
result += f"{counter}. {element}\n"
return result
# with generator syntax
def __str__(self):
return "\n".join(f"{c}. {elem}" for c, elem in enumerate(self.a_list, 1))
Your __str__() function does not return a string if nothing is added to the object before the assertion. An assertion error would be generated even if the function was called correctly.

Python is not calling this function and I cannot find out why

Trying to make this code work and it's not calling my 'makeDictionary' function in my class. I cannot figure out why. Any thoughts?
from StringCount import *
def main():
products = StringCount()
doc = input("Enter File Location: ")
doc_object = open(doc, "r").read()
items = doc_object.split()
products.makeDictionary(items)
itemList = products.sortItems()
print(f"{'Product':^15}{'Quantity':^10}")
print("-" * 25)
for p in range(len(itemList)):
item, count = itemList[p]
print(f"{item:<15}{count:>10}")
if __name__ == "__main__":
main()
Edit: Sorry for the garbage post, I'm still trying to figure it all out. Here is my class code.
from operator import itemgetter
class StringCount:
def __init__(self):
self.notes = {}
self.key = []
self.value = []
def makeDictionary(self, items):
for item in items:
item.strip('')
if item == int:
self.value.append(item)
if item == str:
self.key.append(item)
for i in range(len(self.key) and len(self.value)):
self.notes[self.key[i]] = self.value[i]
EDIT #2: Okay, so to clarify my issue. I'm not looking for clarification on the class. Running this program in python I enter the file location, and it skips over the 'makeDictionary' method entirely. Now I just don't see why and I am sure there is a small reason. If anyone can help out that would be appreciated.
As #jasonharper points out,
if item == int:
Won't work. Instead use
if isinstance(item, int):
Same thing for str

'MarkovGenerator' object has no attribute 'together'

I come up with a problem about the class and I don't know the reason, does anyone can help me out?
The problem is in def together(), here are my code.
class MarkovGenerator(object):
def __init__(self, n, max):
self.n = n # order (length) of ngrams
self.max = max # maximum number of elements to generate
self.ngrams = dict() # ngrams as keys; next elements as values
beginning = tuple(["That", "is"]) # beginning ngram of every line
beginning2 = tuple(["on", "the"])
self.beginnings = list()
self.beginnings.append(beginning)
self.beginnings.append(beginning2)
self.sentences = list()
def tokenize(self, text):
return text.split(" ")
def feed(self, text):
tokens = self.tokenize(text)
# discard this line if it's too short
if len(tokens) < self.n:
return
# store the first ngram of this line
#beginning = tuple(tokens[:self.n])
#self.beginnings.append(beginning)
for i in range(len(tokens) - self.n):
gram = tuple(tokens[i:i+self.n])
next = tokens[i+self.n] # get the element after the gram
# if we've already seen this ngram, append; otherwise, set the
# value for this key as a new list
if gram in self.ngrams:
self.ngrams[gram].append(next)
else:
self.ngrams[gram] = [next]
# called from generate() to join together generated elements
def concatenate(self, source):
return " ".join(source)
# generate a text from the information in self.ngrams
def generate(self,i):
from random import choice
# get a random line beginning; convert to a list.
#current = choice(self.beginnings)
current = self.beginnings[i]
output = list(current)
for i in range(self.max):
if current in self.ngrams:
possible_next = self.ngrams[current]
next = choice(possible_next)
output.append(next)
# get the last N entries of the output; we'll use this to look up
# an ngram in the next iteration of the loop
current = tuple(output[-self.n:])
else:
break
output_str = self.concatenate(output)
return output_str
def together(self):
return "lalala"
if __name__ == '__main__':
import sys
import random
generator = MarkovGenerator(n=2, max=16)
for line in open("us"):
line = line.strip()
generator.feed(line)
for i in range(2):
print generator.generate(i)
print generator.together()
But I got the error saying:
Traceback (most recent call last):
File "markovoo2.py", line 112, in <module>
print generator.together()
AttributeError: 'MarkovGenerator' object has no attribute 'together'
Does anyone know know the reason?
You have indented the def together() function definition too far, it is part of the def generate() function body.
Un-indent it to match the other functions in the class body.
It looks your def together is indented too deeply. It is inside the generate method. Move it out one indentation level.

loop fails when increasing string from elements in list

I have some problem with sequence generator. I have a file where each line contain one fragment (8 letters). I load it from file in to list, where each element is one fragment. It is DNA so it should go that way:
1. Takes first 8-letter element
2. Check for element in which first 7 letters is the same as last 7 letters in first.
3. Add 8th letter from second element in to sequence.
It should look like this:
ATTGCCAT
TTGCCATA
TGCAATAC
So sequence: ATTGCCATAC
Unfortunately it only add one element. :( First element is given (we knew it). I do it that way its first in file (first line).
Here is the code:
from os import sys
import random
def frag_get(seqfile):
frags = []
f_in = open(seqfile, "r")
for i in f_in.readlines():
frags.append(i.strip())
f_in.close()
return frags
def frag_list_shuffle(frags):
random.shuffle(frags)
return frags
def seq_build(first, frags):
seq = first
for f in frags:
if seq[-7:] == f[:7]:
seq += f[-1:]
return seq
def errors():
pass
if __name__ == "__main__":
frags = frag_get(sys.argv[1])
first = frags[0]
frags.remove(first)
frags = frag_list_shuffle(frags)
seq = seq_build(first, frags)
check(sys.argv[2], seq)
spectrum(sys.argv[2], sys.argv[3])
I have deleted check and spectrum functions because it's simple calculations e.g. length comparison, so it is not what cause a problem as I think.
I will be very thankfully for help!
Regards,
Mateusz
Because your fragments are shuffled, your algorithm needs to take that into account; currently, you're just looping through the fragments once, which is unlikely to include more than a few fragments if they're not in the right order. For example, say you have 5 fragments, which I'm going to refer to by their order in your sequence. Now the fragments are slightly out of order:
1 - 3 - 2 - 4 - 5
Your algorithm will start with 1, skip 3, then match on 2, adding a base at the end. Then it'll check against 4 and 5, and then finish, never reaching fragment 3.
You could easily fix this by starting your loop again each time you add a base, however, this will scale very badly for a large number of bases. Instead, I'd recommend loading your fragments into a trie, and then searching the trie for the next fragment each time you add a base, until you've added one base for each fragment or you can no longer find a matching fragment.
works for me:
>>> seq = "ATTGCCAT"
>>> frags = ["TTGCCATA", "TGCCATAC"]
>>> for f in frags:
... if seq[-7:] == f[:7]:
... seq += f[-1:]
...
>>> seq
'ATTGCCATAC'
You have a spelling error in your example, TGCAATAC should be TGCCATAC. But fixing that it works.
For fun and interest, I've rewritten the problem using OO. See what you think:
import collections
import sys
import random
usage = """
Usage:
sequence fname expected
Where
fname: name of file containing fragments
expected: result-string which should be obtained by chaining from first fragment.
"""
class Frag(str):
MATCHLEN = 7
def __new__(cls, s=''):
return str.__new__(cls, s.strip())
def head(self):
return Frag(self[:Frag.MATCHLEN])
def tail(self):
return Frag(self[Frag.MATCHLEN:])
def nexthead(self):
return Frag(self[-Frag.MATCHLEN:])
def check(self, s):
return self.__eq__(s)
def __add__(self, s):
return Frag(str(self).__add__(s))
class Fraglist(list):
#classmethod
def fromFile(cls, fname):
with open(fname, "r") as inf:
lst = [Frag(ln) for ln in inf]
return cls(lst)
def shuffle(self):
random.shuffle(self)
class Sequencer(object):
def __init__(self, seq=None):
super(Sequencer, self).__init__()
self.sequences = collections.defaultdict(list)
if seq is not None:
for frag in seq:
self.sequences[frag.head()].append(frag.tail())
def build(self, frag):
res = [frag]
match = frag.nexthead()
while match in self.sequences:
next = random.choice(self.sequences[match])
res.append(next)
match = (match + next).nexthead()
return Frag(''.join(res))
def main():
if len(sys.argv) != 3:
print usage
sys.exit(-1)
else:
fname = sys.argv[1]
expected = sys.argv[2]
frags = Fraglist.fromFile(fname)
frag1 = frags.pop(0)
frags.shuffle()
seq = Sequencer(frags)
result = seq.build(frag1)
if result.check(expected):
print "Match!"
else:
print "No match"
if __name__=="__main__":
main()

Categories

Resources