How to make this code identify what has been input before? - python

For a homework assignment we have to write code that will do the following:
Write a program to read in multiple lines of input until a blank line
is entered. Each line of input will consist of multiple words. If you
have seen the word before, you should print it out. After the user has
finished entering input, your program should print out how many
repeated words it saw.
So far I have done this:
lineList = []
wordList = []
count = 0
line = input("Words: ")
while line:
for x in line.split():
if x in lineList:
count += 1
wordList.append(x)
print(x)
lineList.append(line)
line = input("Words: ")
print('You repeated '+ str(count) +' word(s).')
My code doesn't loop back to the beginning, and it just stops. There is no error; the thing just stops running. What can I do to make it run again, and how do I make it work?

First and foremost, you have an infinite loop. line is never updated with any values, since the condition that it's hiding under is never true. lineList won't contain x at the beginning of the program, so it's just going to be stuck there.
The obvious fix to that would be to move the input line again over a couple of spaces...
while line:
for x in line.split():
if x in lineList:
count += 1
wordList.append(x)
print(x)
lineList.append(line)
line = input("Words: ")
...but that doesn't quite do it either.
Your next problem is that your condition is incorrect. You shouldn't care if a word appears in lineList - in fact, it's a superfluous variable that would only serve to confuse you later. You want to be checking against wordList.
So, that makes the code this (without lineList):
line = input("Words: ")
while line:
for x in line.split():
if x in wordList:
count += 1
wordList.append(x)
print(x)
line = input("Words: ")
The last condition - the word should be echoed only if you've seen it before - I leave as an exercise for the reader.

The problem isn't that it stops, it's the opposite: it keeps going in an infinite loop, without asking for input, because it only asks for more input when and if it finds a word that's already in the linelist. Unindent the request for input by two levels, so that you ask for input after processing an entire line. You also have to add to the count and print the word if it is in the list, or add it to the list if it is not already in the list. You also have to add the word to wordList, not lineList. In fact, you don't need lineList for anything, either.
wordList = []
count = 0
line = input("Words: ")
while line:
for x in line.split():
if x in wordList:
count += 1
print(x)
else:
wordList.append(x)
line = input("Words: ")
print('You repeated', str(count), 'word(s).')

Related

Why does my variable suddenly stop counting after the first loop?

I'm writing a program that counts the amount of letters in a word. Everything seems to work fine except for the fact that my variable used for counting the number of letters (numberOfLetters) suddenly stops counting after the first loop. Here is my code:
import random
# Choosing a random word
with open("Random Words.txt", "r") as file:
allText = file.read()
allWords = list(map(str, allText.split('\n')))
chosenWord = random.choice(allWords)
# Resetting variables
correctLetters = []
incorrectLetters = []
hiddenWord = []
numberOfLetters = 0
for i in range(12): # Loop 12 times
print(numberOfLetters)
for letter in chosenWord: # Loop once for every letter in the word
numberOfLetters = numberOfLetters + 1 # Count the number of letters in the word
if ''.join(correctLetters) in chosenWord: # If a letter is guessed, show it. Otherwise, censor it.
hiddenWord.append(chosenWord[numberOfLetters])
else:
hiddenWord.append('_')
print(hiddenWord)
hiddenWord = []
userGuess = input('Guess a letter:')
if userGuess in chosenWord: # If the user guesses a letter correctly, we'll add it to the list of letters guessed
correctLetters.append(userGuess)
print(userGuess)
else:
incorrectLetters.append(userGuess)
# print(hiddenWord)
print('Chosen word:' + chosenWord)
# UserGuess = input('\n')
print('Number of letters:')
print(numberOfLetters)
print('Correct letters:')
print(correctLetters)
print('Incorrect letters:')
print(incorrectLetters)
Output:
0
['b']
['u']
['n']
['d']
['a']
['n']
['t']
Traceback (most recent call last):
File "C:\Users\Dr Hani Attar\PycharmProjects\Hangman\main.py", line 34, in <module>
hiddenWord.append(chosenWord[numberOfLetters])
IndexError: string index out of range
Process finished with exit code 1
String indexing is 0-based. But your code is treating it as 1-based. Note how in your sample output the 'a' in the chosen word 'abundant' is never printed -- you started with index 1.
chosenWord[numberOfLetters] will fail when numberOfLetters == len(chosenWord) -- which it will do in the final pass through the loop for letter in chosenWord:
One thing you could do is to use chosenWord[numberOfLetters-1] and include the line
numberOfLetters = 0
at the beginning of the for-loop. Otherwise you will have another string index out of range error in the second pass through the loop.
The for-loop itself seems unmotivated. Why assume that the user will make exactly 12 guesses? It would make more sense to use a while-loop. Loop while there are still letters to guess.

Python: Same word twice in a list

I'm trying to write a program that stops if the same word is given twice. This code almost does the job, but it stops only if the duplicate words are given sequentially. Thanks for your help.
list = []
double = None
while True:
word = input("word: ")
lista.append(word)
if douple == word:
print(f"You gave {len(list)} words")
break
double = word
You need to check if the word is already in the list
seen = []
while True:
word = input("word: ")
if word in seen:
print(f"You gave {len(seen)} words")
break
seen.append(word)
If you just want to tell duplicates, and don't need to keep the order, you can use a set instead; this will be more efficient for a large number of words:
seen = set()
while True:
word = input("word: ")
if word in seen:
print(f"You gave {len(seen)} words")
break
seen.add(word)
Finally, in sufficiently recent Python (at least 3.6 or 3.7, depending on how you take things), you can do both by using a dictionary; this is both efficient and keeps the order in which the words were entered:
seen = {}
while True:
word = input("word: ")
if word in seen:
print(f"You gave {len(seen)} words")
break
seen[word] = None
Change your code to what is given below:
words_list = []
while True:
word = input("Word: ")
if word not in words_list: #Checks if the word is in the list. If it exists in list, it would return False
words_list.append(word)
else:
print(f"You gave {len(words_list)} words")
break
I have changed a few things:
Don't use list as a variable name as it is a keyword in Python.
Check for duplicate words using not in before you append it to the list. If word exists in the list, the loop would break.
This should do the work. You can always comment down if you need clarification or if the code dosen't work.

Python - importing 127,000+ words to a list, but function only returning partial results

this function is meant to compare all 127,000 + words imported from a dictionary file to a user inputed length. It then should return the amount of words that are equal to that length. It does do this to an extent.
If I enter "15" it returns "0".
If I enter "4" it returns "3078".
I am positive that there are words that are 15 characters in length but it returns "0" anyways.
I should also mention that if I enter anything greater that 15 the result is still 0 when there is words greater that 15.
try:
dictionary = open("dictionary.txt")
except:
print("Dictionary not found")
exit()
def reduceDict():
first_list = []
for line in dictionary:
line = line.rstrip()
if len(line) == word_length:
for letter in line:
if len([ln for ln in line if line.count(ln) > 1]) == 0:
if first_list.count(line) < 1:
first_list.append(line)
else:
continue
if showTotal == 'y':
print('|| The possible words remaing are: ||\n ',len(first_list))
My reading of:
if len([ln for ln in line if line.count(ln) > 1]) == 0:
is that the words in question can't have any repeated letters which could explain why no words are being found -- once you get up to 15, repeated letters are quite common. Since this requirement wasn't mentioned in the explanation, if we drop then we can write:
def reduceDict(word_length, showTotal):
first_list = []
for line in dictionary:
line = line.rstrip()
if len(line) == word_length:
if line not in first_list:
first_list.append(line)
if showTotal:
print('The number of words of length {} is {}'.format(word_length, len(first_list)))
print(first_list)
try:
dictionary = open("dictionary.txt")
except FileNotFoundError:
exit("Dictionary not found")
reduceDict(15, True)
Which turns up about 40 words from my Unix words file. If we want to put back the unique letters requirement:
import re
def reduceDict(word_length, showTotal):
first_list = []
for line in dictionary:
line = line.rstrip()
if len(line) == word_length and not re.search(r"(.).*\1", line):
if line not in first_list:
first_list.append(line)
if showTotal:
print('The number of words of length {} is {}'.format(word_length, len(first_list)))
print(first_list)
Which starts returning 0 results around 13 letters as one might expect.
In your code, you don't need the this line -
for letter in line:
In your list comprehension, if your intention is to loop over all the words in the line use this -
if len([ln for ln in line.split() if line.count(ln) > 1]) == 0:
In you code the loop in list comprehension loops over every character and checks if that character appears more than once in line. That way if your file contains chemotherapeutic it will not be added to the list first_list as there are letters that appears multiple times. So, unless your file contains word with more than 14 letters where all letters appear only once, you code will fail to find them.

has_no_e() exercise from Think Python

This is from Think Python. Trying to go through each line(One word in each line) of a file and only printing out every word that does not contain the letter e.
I've spend like 4 hours trying different ways to filter the file through my function, but i give in. It seems it that it only filter out the first e it finds in a word: if a word has two e's than it prints it out anyways.
def has_no_e():
file_name = raw_input('Enter the full path and file name: ')
fin = open(file_name)
line = fin.readline()
for line in fin:
word = line.strip()
print word
for letter in word:
if letter == 'e':
continue
print word
has_no_e()
My code is indented btw, i think it messes up when i ctrl + v
If there's a way to make it my code shorter please let me know :]
with open(filename) as f:
for line in f:
if not 'e' in line: print line.strip()
Some comments:
use with when working with files, although it's a newer construct in python, it helps you to manage your files (i.e. closing it again when not needed anymore)
word = line.strip() makes your code not very readable. Use line = line.strip() (you will only use either line or word, not both, I assume)
So why was your code not working?
for letter in word:
if letter == 'e':
continue
print word
Here you split the word into its letters, then you check if the letter is equal to e. If that's not the case, you print the word, otherwise you jump to the next letter. So you print the word as many times as there are letters different from 'e'.
A way to solve this would be to define a boolean, which tells you if there was an e in the word:
hasE = False
for letter in word:
if letter == 'e':
hasE = True
break
if not hasE: print word
Note that Python also has a fancy way to solve problems like this:
for letter in word:
if letter == 'e': break
else:
print word
It looks like pfnuesel went over the main reason the code wasn't working when he wrote:
"Here you split the word into its letters, then you check if the
letter is equal to e. If that's not the case, you print the word,
otherwise you jump to the next letter. So you print the word as many
times as there are letters different from 'e'."
Here's the way I solved exercise 9.2 in Think Python:
def has_no_e(word):
return "e" not in word
fin = open('words.txt')
for line in fin:
word = line.strip()
if has_no_e(word):
print word

Python: How to make a function that asks for the exact amount of words?

Here's what I have so far:
import string
So I have the user write a 5 worded sentence asking for only 5 words:
def main(sentence = raw_input("Enter a 5 worded sentence: ")):
if len(words)<5:
words = string.split(sentence)
wordCount = len(words)
print "The total word count is:", wordCount
If the user inputs more than 5 words:
elif len(words)>5:
print 'Try again. Word exceeded 5 word limit'
Less than 5 words:
else:
print 'Try again. Too little words!'
It keeps stating that:
UnboundLocalError: local variable 'words' referenced before assignment
Your problem is that you are calling len(words) before the variable words exists. This is in the second line of your second code block.
words = []
while len(words) != 5:
words = raw_input("Enter a 5 worded sentence: ").split()
if len(words) > 5:
print 'Try again. Word exceeded 5 word limit'
elif len(words) < 5:
print 'Try again. Too little words!'
Note that in python, default arguments are bound at time of function definition rather than at function call time. This means your raw_input() will fire when main is defined rather then when main is called, which is almost certainly not what you want.
Read your own output :): the 'words' variable is referenced before assignment.
In other words, you are calling len(words) before saying what 'words' means!
def main(sentence = raw_input("Enter a 5 worded sentence: ")):
if len(words)<5: # HERE! what is 'words'?
words = string.split(sentence) # ah, here it is, but too late!
#...
Try defining it before attempting to use it:
words = string.split(sentence)
wordCount = len(words)
if wordCount < 5:
#...
Take the inputs using raw_input().
Do the wordcount using Split()
and then re-read if it is not equal to 5.
UnboundLocalError: local variable 'words' referenced before assignment
This means exactly what it says. You are trying to use words before the part where you figure out what the words actually are.
Programs proceed step-by-step. Be methodical.

Categories

Resources