Repeat a function every 5 times a loop runs - python-2.7

Is there a way to repeat a single function in a while loop one in every 5 times the loop runs? I am trying to create a bot to help me with my Latin revision but I don't want the option to close the program to crop up every time I answer a question, it would be better if it only happened 1 out of 10 times.
import random
exit = "no"
print "welcome to latin learner v1"
wordtype = raw_input("what would you like to learn (nouns verbs everything)")
if wordtype == "nouns":
declension = raw_input("declension 1-5")
if declension == "1":
while "no" in exit:
wordno = random.randint(1,30)
noun1L = ["ancilla","aqua","cena","copiae","cura","dea","domina","epistula","femina","filia","hora","ianua","insula","ira","nauta","patria","pecunia","poena","porta","puella","regina","Roma","silva","taberna","terra","turba","via","victoria","villa","vita"]
answer = raw_input(noun1L[wordno])
noun1E = ["slave-girl" or"slave-woman","water","dinner" or "meal","forces" or "troops","care" or "worry","goddess","mistress","letter","woman","daughter","hour","door","island" or "block of flats","anger","sailor","country" or "homeland","money","punishment","gate","girl","queen","Rome","wood","shop" or "inn","ground" or "land" or "country","crowd","street" or "road" or "way","victory","house" or "country villa","life"]
if noun1E[wordno] == answer:
print "correct"
else:
print "incorrect"
print noun1E[wordno]
for i in range[1,5]:
exit = raw_input("would you like to quit (yes/no)")

To solve your issue, we can add a question counter and use the modulus operator (%) to trigger the exit option on every fifth question.
However, there are some other problems to address. For example, this:
,"dinner" or "meal",
is just wishful thinking -- it doesn't work that way. We can turn this into a list of possible answers. Next, whenever we have parallel arrays like noun1L and noun1E, it usually means we're missing a data structure. Finally, don't store the data in the code, separate them.
Here's my rework of your code addressing the above issues:
import random
noun1 = {
"ancilla": ["slave-girl", "slave-woman"],
"aqua": ["water"],
"cena": ["dinner", "meal"],
"copiae": ["forces", "troops"],
"cura": ["care", "worry"],
"dea": ["goddess"],
"domina": ["mistress"],
"epistula": ["letter"],
"femina": ["woman"],
"filia": ["daughter"],
"hora": ["hour"],
"ianua": ["door"],
"insula": ["island", "block of flats"],
"ira": ["anger"],
"nauta": ["sailor"],
"patria": ["country", "homeland"],
"pecunia": ["money"],
"poena": ["punishment"],
"porta": ["gate"],
"puella": ["girl"],
"regina": ["queen"],
"Roma": ["Rome"],
"silva": ["wood"],
"taberna": ["shop", "inn"],
"terra": ["ground", "land", "country"],
"turba": ["crowd"],
"via": ["street", "road", "way"],
"victoria": ["victory"],
"villa": ["house", "country villa"],
"vita": ["life"],
}
print("Welcome to Latin Learner v1")
wordtype = raw_input("What would you like to learn (nouns verbs everything): ")
if wordtype == "nouns" or wordtype == "everything":
declension = raw_input("Declension 1-5: ")
if declension == "1":
count = 1
while True:
word = random.choice(list(noun1))
answer = raw_input(word +": ")
if answer.lower() in noun1[word]:
print("Correct.")
else:
print("Incorrect: " + ", ".join(noun1[word]))
if count % 5 == 0:
answer = raw_input("would you like to quit (yes/no): ")
if "y" in answer.lower():
break
count += 1

Related

Chatbot problem - infinite recursion - Codecademy question

I'm learning how to code using Codecademy and I am really stuck on a question, and would love to be pointed in the right direction!
The code for the most part works, I just cannot get it to respond to the .match_reply function correctly. The idea is that the chatbot should identify the regex in self.alienbabble and respond with the appropriate answer. However, it is bugging out with an infinite recursion of all the responses of that function.
# importing regex and random libraries
import re
import random
class AlienBot:
# potential negative responses
negative_responses = ("no", "nope", "nah", "naw", "not a chance", "sorry")
# keywords for exiting the conversation
exit_commands = ("quit", "pause", "exit", "goodbye", "bye", "later")
# random starter questions
random_questions = (
"Why are you here? ",
"Are there many humans like you? ",
"What do you consume for sustenance? ",
"Is there intelligent life on this planet? ",
"Does Earth have a leader? ",
"What planets have you visited? ",
"What technology do you have on this planet? "
)
def __init__(self):
self.alienbabble = {'describe_planet_intent': '.*\s*your planet.*','answer_why_intent': 'why\sare.*', 'cubed_intent': '.*cube.*(\d+)'}
# Define .greet() below:
def greet(self):
self.name = input("Hello. What is your name?")
will_help = input(f"Hi {self.name}, I'm Etcetera. I'm not from this planet. Will you help me learn about your planet? ")
if will_help in self.negative_responses:
print ("Ok, have a nice Earth day!")
return
self.chat()
# Define .make_exit() here:
def make_exit(self, reply):
for word in self.exit_commands:
if word in reply:
print ("Ok, have a nice Earth day!")
return True
# Define .chat() next:
def chat(self):
reply = input(random.choice(self.random_questions)).lower()
while not self.make_exit(reply):
reply = input(self.match_reply(reply))
# Define .match_reply() below:
def match_reply(self, reply):
for key, value in self.alienbabble.items():
intent = key
regex = value
#regex = 'describe_planet_intent'
#reply = input(random.choice(self.random_questions)).lower()
found_match = re.match(regex, reply)
if found_match and intent == 'describe_planet_intent':
return self.describe_planet_intent()
elif found_match and intent == 'answer_why_intent':
return self.answer_why_intent()
elif found_match and intent == 'cubed_intent':
return self.cubed_intent(found_match.groups()[0])
else:
return self.no_match_intent()
# Define .describe_planet_intent():
def describe_planet_intent(self):
responses = ("My planet is a utopia of diverse organisms and species. ", "I am from Opidipus, the capital of the Wayward Galaxies. ")
return random.choice(responses)
# Define .answer_why_intent():
def answer_why_intent(self):
responses = ("I come in peace. ", "I am here to collect data on your planet and its inhabitants. ", "I heard the coffee is good. ")
return random.choice(responses)
# Define .cubed_intent():
def cubed_intent(self, number):
number = int(number)
cubed_number = number * number * number
return (f"The cube of {number} is {cubed_number}. Isn't that cool? ")
# Define .no_match_intent():
def no_match_intent(self):
responses = ("Please tell me more. ", "Tell me more! ", "Why do you say that? ", "I see. Can you elaborate? ", "Interesting. Can you tell me more? ", "I see. How do you think? ", "Why? ", "How do you think I feel when you say that? ")
return random.choice(responses)
# Create an instance of AlienBot below:
my_bot = AlienBot()
my_bot.greet()
I feel like there is a really simple solution to this, I've only been coding for 1 week so this is really new to me, and I appreciate your help :)
The answer is indeed simple. Let's reduce your code to a minimally reproducible one:
def match_reply(self, reply):
for key, value in self.alienbabble.items():
# I omitted the 3 lines that were here - defining 'intent', 'regex_pattern' and 'regex' -
# since at this point they're yet not used
reply = input(self.match_reply(reply)) # oops! self.match_reply is called again!
As you can see, you recursively call self.match_reply without anything to stop it.
EDIT:
There are another 2 things you need to fix:
Let's change match_reply:
a. Let's give it the more appropriate name match_alien_response.
b. Let's make it do what it should: just match a reply. Thus, we don't need it to get another input from the user.
c. Let's make sure it iterates all the keys in alienbabble and doesn't return immediately.
d. We need to use re.findall to get all matches in a string
All these changes give us the following code:
def match_alien_response(self, userReply):
found = False
for intent, regPattern in self.alienbabble.items():
found_match = re.findall(regPattern, userReply)
if found_match and intent == 'describe_planet_intent':
return self.describe_planet_intent()
elif found_match and intent == 'answer_why_intent':
return self.answer_why_intent()
elif found_match and intent == 'cubed_intent':
return self.cubed_intent(found_match[0])
if not found:
return self.no_match_intent()
Inside no_match_intent, it should be responses = instead of responses:

Python 2.7, trouble printing docstrings (doc comments) "function has no attribute _doc_" error

I'm working on LPTHW ex 41, where we modify a bunch of print statements to use a docstring style and then use a runner to print them.
The code originally was like this:
Function()
Print "Several lines of printed material"
Revised, the functions begin:
Function()
"""doc comment"""
A runner connects all the functions ("rooms") like so, with the goal being to print doc comments instead of print commands.
ROOMS = {
'death': death,
'central_corridor': central_corridor,
'laser_weapon_armory': laser_weapon_armory,
'the_bridge': the_bridge,
'escape_pod': escape_pod
}
def runner(map, start):
next = start
while True:
room = map[next]
print "\n----------------"
print room._doc_
next = room()
runner(ROOMS, 'central_corridor')
But I keep getting the error
'function" object has no attribute '_doc_'
Example room:
def central_corridor():
"""You wanna blow thing up.
You running toward place for to get bomb.
Emeny approach!
1 = shoot at enemy
2 = avoid emenemeny
3 = use bad pick up line on emenie
4 = hint"""
#print(_doc_)
action = int(raw_input("> "))
if action == 1:
print "He shoot you first."
return 'death'
elif action == 2:
print "No he still gots you."
return 'death'
elif action == 3:
print "Oh yeah sexy boy."
print "You get past laughing enemy."
return 'laser_weapon_armory'
elif action == 4:
print "Emeny like good joke."
return 'central_corridor'
else:
print "You enter wrong input"
return 'central_corridor'
Can anyone tell me how to get the doc comments to print? Thanks!
Noticed doc needs two underscores. Fixed
_doc_
__doc__

Python: Trying to loop through a string to find matching characters

I am trying to create a simple "guess the word" game in Python. My output is something like:
String: _____ _____
Guess a word: 'e'
String:_e__o __e_e
Guess a word: 'h'
(and so on)
String: hello there
I have a function to do this, and within this function I have this code:
def guessing(word):
count = 0
blanks = "_" * len(word)
letters_used = "" #empty string
while count<len(word):
guess = raw_input("Guess a letter:")
blanks = list(blanks)
#Checks if guesses are valid
if len(guess) != 1:
print "Please guess only one letter at a time."
elif guess not in ("abcdefghijklmnopqrstuvwxyz "):
print "Please only guess letters!"
#Checks if guess is found in word
if guess in word and guess not in letters_used:
x = word.index(guess)
for x in blanks:
blanks[x] = guess
letters_used += guess
print ("".join(blanks))
print "Number of misses remaining:", len(word)-counter
print "There are", str(word.count(guess)) + str(guess)
guess is the raw input I get from the user for a guess, and letters_used is just a collection of guesses that the user has already input. What I'm trying to do is loop through blanks based on the word.index(guess). Unfortunately, this returns:
Guess a letter: e
e___
Yes, there are 1e
Help would be much appreciated!
Your code was almost correct. There were few mistakes which I have corrected:
def find_all(needle, haystack):
"""
Finds all occurances of the string `needle` in the string `haystack`
To be invoked like this - `list(find_all('l', 'hello'))` => #[2, 3]
"""
start = 0
while True:
start = haystack.find(needle, start)
if start == -1: return
yield start
start += 1
def guessing(word):
letters_uncovered_count = 0
blanks = "_" * len(word)
blanks = list(blanks)
letters_used = ""
while letters_uncovered_count < len(word):
guess = raw_input("Guess a letter:")
#Checks if guesses are valid
if len(guess) != 1:
print "Please guess only one letter at a time."
elif guess not in ("abcdefghijklmnopqrstuvwxyz"):
print "Please only guess letters!"
if guess in letters_used:
print("This character has already been guessed correctly before!")
continue
#Checks if guess is found in word
if guess in word:
guess_positions = list(find_all(guess, word))
for guess_position in guess_positions:
blanks[x] = guess
letters_uncovered_count += 1
letters_used += guess
print ("".join(blanks))
print "Number of misses remaining:", len(word)-letters_uncovered_count
print "There are", str(word.count(guess)) + str(guess)
else:
print("Wrong guess! Try again!")

Multiple Errors in Hangman program

I've been teaching my self to program in python lately and decided to make this game. I have been successful for the majority of it except for a few things
When an incorrect letter is inputted, the letter is appended to the wrong letter array for as many spots in the gamespace array that the userletter does equal.Example: if I type in "the" for the wordtarget, I get t, h and e printed 2 times into wrong letter array. No matter what the letter gets out into wrong letter array
Code:
wordTarget = raw_input("enter word here: ").lower ()
gameSpace = ["_"] * Len(wordTarget)
wrongLetter = []
def main():
for x in range(0, len(wordTarget)):
while (gameSpace[x] != wordTarget[x]):
getLetter()
for i in range(0,len(wordTarget)):
if (wordTarget[i] == userLetter):
gameSpace[i] = userLetter
elif (wordTarget[i] != userLetter):
print "letter is incorrect, try again"
wrongLetter.append(userLetter)
print ("Incorrect Letters: %s" % wrongLetter)
print ("Correct Letters: %s" % gameSpace)
if (gameSpace == wordTarget):
print "Congratulations! You won"
main()
I'm guessing the problem lies with the for loops I'm running and the way I'm checking for right answer but can't figure it out.
The loop checking the letter seems to be your issue. Try replacing it with:
position = 0
ptr = wordTarget.find(userLetter, position)
while ptr != -1:
gameSpace[ptr] = userLetter
position = ptr + 1
ptr = wordTarget.find(userLetter, position)
if position == 0: # no match ever found
print "letter is incorrect, try again"
wrongLetter.append(userLetter)
Also replace the original for loop with while ("".join(gameSpace) != wordTarget):, and you should be good to go.

how to loop a set amount of times

Im writing a code that simulates the game word scrabble. What im trying to do is that it asks the user to unscrabble the word, and if they fail at it once they get another chance and so on for 3 chances. after 3 chances the program should tell them that they couldn't guess it within the chances limit and the program should tell them the word.
rand_artist = artist_names[random.randrange(len(artist_names))]
tries = 0
while tries < 3:
rand_input = enterbox("Unscrabble the following: {}".
format(txt), "Word Scrabble")
if rand_input != rand_artist:
msgbox("Try again!", "Word Scrabble")
tries +=1
elif rand_input == rand_artist:
msgbox("Congratulations! You guessed the word!")
tries +=3
elif tries > 2:
msgbox("You used up three chances! The word was {}".
format(txt), "Word Scrabble!")
Your code had several problems, some noted in my comment on the question. The following works as you seem to want.
from random import choice, shuffle
artist_names = ['Renoir', 'VanGogh', 'Rembrant', 'Homer', 'Pyle',]
artist = choice(artist_names)
alist = list(artist)
shuffle(alist)
scram = ''.join(alist)
for tries in range(1, 4):
guess = input("Unscrabble {}: ".format(scram))
if guess == artist:
print("Congratulations! You guessed the word!")
break
elif tries < 3:
print("Try again!")
else:
print("Failed three chances! The word was {}.".format(artist))