Python find words within a user input word game - python

I'm trying to write a program that allows the user to input a word then find all words of length 4 or greater hidden within that word that are in a word text file. So far my code can detect the words in the user inputted word that aren't jumbled. For example if I type in houses, the output will show house, houses, ho, us, use, uses. It should also recognize hose, hoses, shoe, shoes, hues, etc.
I know itertools is the simplest solution but I want to use a different method using only loops, dictionaries, and lists.
Here is my code so far:
def main():
filename = open('dictionary.txt').readlines()
word_list = []
for line in filename:
word_list.append(line.strip())
print 'Lets Play Words within a Word!\n'
word = raw_input('Enter a word: ')
words_left = 0
for words in word_list:
letters = list(words)
if words in word:
print words
words_left += 1
else:
False
The output format I'm trying to create should look like so:
Lets play Words within a Word!
Enter a word: exams #user inputted word
exams --- 6 words are remaining
> same #user types in guess
Found! # prints 'Found!' if above word is found in the dictionary.txt file
exams --- 5 words are remaining
> exam
Found!
exams --- 4 words are remaining
> mesa
Found!
exams --- 3 words are remaining
> quit() #if they type this command in the game will end
So my question is, after entering the base word (in the ex it's EXAMS), how do I determine the total number of words within that word and if the user inputted word guesses are in the text file? Also print if the word was found.

something like this should work...
wordlist=[list of words]
solutionlist=[]
userword=[userword[i] for i in range(len(userword))]
for word in wordlist:
inword=True
letters=[word[j] for j in range(len(word))]
for letter in set(letters):
if letters.count(letter)>userword.count(letter):
inword=False
break
if inword:
solutionlist.append(word)
for line in solutionlist:
print line

This works:
# read from file in actual implementation
all_words = [
"foo", "bar", "baz", "hose", "hoses", "shoe", "shoes", "hues", "house",
"houses", "ho", "us", "use", "uses", "shoe", "same", "exam", "mesa", "mass"]
RETAIN_ORDERING = False
def matches(inp, word):
if inp[0] == word[0]:
return (
True if len(word) == 1 else
False if len(inp) == 1 else
matches(inp[1:], word[1:]))
else:
return matches(inp[1:], word) if len(inp) >= 2 else False
# with sorting enabled, "houses" will also match "shoe"; otherwise not
def maybe_sort(x):
return x if RETAIN_ORDERING else ''.join(sorted(x))
inp = raw_input("enter a word: ")
results = [word for word in all_words if matches(maybe_sort(inp), maybe_sort(word))]
print results
Output:
$ python matches.py
enter a word: houses
['hose', 'hoses', 'shoe', 'shoes', 'hues', 'house', 'houses', 'ho', 'us', 'use', 'uses', 'shoe']
$ python matches.py
enter a word: exams
['same', 'exam', 'mesa']
If you want to avoid matches like shoe where the ordering of letters is not the same as in the input, just set RETAIN_ORDERING = True.

A naive implementation (using collections.Counter):
>>> all_words = ['foo', 'bar', 'baz', 'hose', 'hoses', 'shoe', 'shoes', 'hues', 'house', 'houses', 'ho', 'us', 'use', 'uses', 'shoe', 'same', 'exam', 'mesa', 'mass']
>>> def find_hidden(user_input):
from collections import Counter
user_word_counts = Counter(user_input)
for word in all_words:
isvalid = True
for letter, count in Counter(word).iteritems():
if user_word_counts[letter] == 0 or user_word_counts[letter] < count:
isvalid = False
break
if isvalid: yield word
>>> list(find_hidden("houses"))
['hose', 'hoses', 'shoe', 'shoes', 'hues', 'house', 'houses', 'ho', 'us', 'use', 'uses', 'shoe']
>>> list(find_hidden("exams"))
['same', 'exam', 'mesa']
Or,
Using permutations:
>>> all_words = ['foo', 'bar', 'baz', 'hose', 'hoses', 'shoe', 'shoes', 'hues', 'house', 'houses', 'ho', 'us', 'use', 'uses', 'shoe', 'same', 'exam', 'mesa', 'mass']
>>> def permutations(s, n): # could use itertools.permutations
if n == 1:
for c in s:
yield c
for i in range(len(s)):
for p in permutation(s[:i]+s[i+1:], n-1):
yield s[i] + p
>>> def find_hidden(input_str):
for word_len in range(2, len(input_str)+1):
for word in permutations(input_str, word_len):
if word in all_words:
yield word
>>> set(find_hidden("houses"))
set(['use', 'hose', 'shoes', 'houses', 'house', 'us', 'hues', 'hoses', 'uses', 'ho', 'shoe'])
>>> set(find_hidden("exams"))
set(['mesa', 'exam', 'same'])

Related

Delete one by one the elements of a list, and then restore the previous ones

I need it to extract the word that starts with a capital letter, if and only if, this word is preceded by the beginning of the sentence or by one of these options (?:,and|and|her friends|,or |or |,)
import re
match_names = ""
input_sense = "Susan gave some cosmetic gifts to her friends Lisa, Veronica and Katy, but only Katy thanked her"
#I concatenate a series of characters that probably nobody uses so that it searches at the beginning
input_sense = "rlt99ll" + input_sense
if match := re.findall(r"(?:rlt99ll|,and|and|her friends|,or |or |,)\s*([A-Z].*?\b)", input_sense):
match_names = match
print("match names: ")
print(match_names)
input_sense = input_sense.replace("rlt99ll", "") #I add this aux-string only for the pattern
n = 0
print("match_auxs : ")
for name in match_names:
match_aux = match_names
for m in match_aux:
if (m == name):
match_aux[n] = ""
n += 1
n = 0
print(match_aux)
I need that output lists:
match names:
['Susan', 'Lisa', 'Veronica', 'Katy']
match_auxs :
['','Lisa', 'Veronica', 'Katy']
['Susan', '', 'Veronica', 'Katy']
['Susan', 'Lisa', '', 'Katy']
['Susan', 'Lisa', 'Veronica', '']
But I get this ( and it's wrong)...
match names:
['Susan', 'Lisa', 'Veronica', 'Katy']
match_auxs :
['', 'Lisa', 'Veronica', 'Katy']
['', '', 'Veronica', 'Katy']
['', '', '', 'Katy']
['', '', '', '']
As said in the comments, assigning a list to another variable doesn't create a copy of it. Along with this, your code can be simplified by using functions like enumerate:
import re
match_names = ""
input_sense = "Susan gave some cosmetic gifts to her friends Lisa, Veronica and Katy, but only Katy thanked her"
#I concatenate a series of characters that probably nobody uses so that it searches at the beginning
input_sense = "rlt99ll" + input_sense
if match_names := re.findall(r"(?:rlt99ll|,and|and|her friends|,or |or |,)\s*([A-Z].*?\b)", input_sense):
print(f"match names: {match_names}")
input_sense = input_sense.replace("rlt99ll", "") #I add this aux-string only for the pattern
n = 0
print("match_auxs: ")
for index, name in enumerate(match_names):
match_aux = match_names.copy()
match_aux[index] = ""
n = 0
print(match_aux)
If you don't want to use copy on the list (for speed), this code will also work:
import re
match_names = ""
input_sense = "Susan gave some cosmetic gifts to her friends Lisa, Veronica and Katy, but only Katy thanked her"
#I concatenate a series of characters that probably nobody uses so that it searches at the beginning
input_sense = "rlt99ll" + input_sense
if match_names := re.findall(r"(?:rlt99ll|,and|and|her friends|,or |or |,)\s*([A-Z].*?\b)", input_sense):
print(f"match names: {match_names}")
input_sense = input_sense.replace("rlt99ll", "") #I add this aux-string only for the pattern
n = 0
print("match_auxs: ")
prev = ""
for index, name in enumerate(match_names):
if index > 0:
match_names[index - 1] = prev
prev = match_names[index]
match_names[index] = ""
print(match_names)
match_names[-1] = prev

Output will not become a string from a list

import os
import random
file = open('getty.txt')
filetext = file.read()
def getline(words,length):
ans=[]
total=0
while (length>total) and 0 != len(words):
word=words.pop(0)
total += len(word)+1 #add 1 for the space
ans.append(word)
#now we are one word too long
if total > length:
words.insert(0,ans.pop())
return ans
def printPara(words,length):
line = []
spaces = []
while len(words) != 0:
line.append(getline(words, length))
for z in range(0,len(line)):
for i in range(0,len(line[z])):
spaces = [[1] * len(line[i]) for i in range (len(line))]
for p in range (0,len(spaces)):
spaces[p][len(spaces[p])-1] = 0
if len(words) + len(spaces) != 0:
addSpace(line,spaces,length)
printLine(line,spaces)
else:
printLine(line,spaces)
def addSpace(line,spaces,length):
totalInt = 0
for i in range (0, len(line)):
totalInt = (len(spaces[i])-2) + len(line[i])
while length < totalInt:
num = random.randint(0, len(spaces) - 2)
spaces[num] += 1
return spaces
def printLine(line, spaces):
for i in range (len(line)):
print(str(line[i]) + (' ' * len(spaces[i])))
def main():
length = 75
textparagraph = filetext.split("\n\n")
para = [0] * len(textparagraph)
for i in range (0, len(textparagraph)):
para[i] = textparagraph[i]
words = [[0] * len(textparagraph) for i in range(len(para))]
for b in range (0,len(para)):
words[b] = para[b].split()
for z in range (0, len(para)):
printPara(words[z],length)
main()
My code outputs only lists of the separate lines and will not concatenate the two lists of words and spaces. How would I get it to output correctly?
Some exampes of output.
['Four', 'score', 'and', 'seven', 'years', 'ago', 'our', 'fathers', 'brought', 'forth', 'on', 'this']
['continent,', 'a', 'new', 'nation,', 'conceived', 'in', 'Liberty,', 'and', 'dedicated', 'to', 'the']
['proposition', 'that', 'all', 'men', 'are', 'created', 'equal.']
['Now', 'we', 'are', 'engaged', 'in', 'a', 'great', 'civil', 'war,', 'testing', 'whether', 'that', 'nation,', 'or']
['any', 'nation', 'so', 'conceived', 'and', 'so', 'dedicated,', 'can', 'long', 'endure.', 'We', 'are', 'met', 'on', 'a']
Expected output "Four score and seven years ago..."
You can use
" ".join(["hello", "world"])
and you'll get
"hello world"

Matching a list's item with another list in python

I have list1 let's say:
items=['SETTLEMENT DATE:', 'CASH ACCOUNT:', 'ISIN:', 'TRADE DATE:', 'PRICE CFA', 'CASH ACCOUNT:', 'SECURITY NAME:']
I have a list2 let's say:
split_t=['{1:F01SCBLMUMUXSSU0438794344}{2:O5991054200218SCBLGHACXSSU04387943442002181454N}{3:{108:2175129}}{4:', ':20:EPACK', 'SALE', 'CDI', ':21:EPACK', 'SALE', 'CDI', ':79:ATTN:MU', 'TEAM', 'KINDLY', 'ACCEPT', 'THIS', 'AS', 'AUTHORISATION', 'TO', 'SETTLE', 'TRADE', 'WITH', 'DETAILS', 'BELOW', 'MARKET:', 'COTE', 'DIVOIRE', 'CLIENT', 'NAME:', 'EPACK', 'OFFSHORE', 'ACCOUNT', 'NAME:', 'STANDARD', 'CHARTERED', 'GHANA', 'NOMINEE', 'RE', 'DATABANK', 'EPACK', 'INVESTMENT', 'FUND', 'LTD', 'IVORY', 'COAST', 'TRADE', 'TYPE:', 'DELIVER', 'AGAINST', 'PAYMENT', 'SCA:', '2CEPACKIVO', 'CASH', 'ACCOUNT:', '420551901501', 'TRADE', 'DETAILS:', 'TRADE', 'DATE:', '17.02.2020', 'SETTLEMENT', 'DATE:', '20.02.2020', 'SECURITY', 'NAME:', 'SONATEL', 'ISIN:', 'SN0000000019', 'CLEARING', 'BIC:', 'SCBLCIABSSUXXX', 'QUANTITY:', '10,500', 'PRICE', 'CFA', '14,500.4667', 'CONSIDERATION', 'CFA', '152,254,900.00', 'TOTAL', 'FEES', '1,796,608.00', 'SETTLEMENT', 'AMOUNT', 'CFA', '150,458,292.35', 'CURRENCY:', 'CFA', 'AC:', 'CI0000010373', 'REGARDS', 'STANDARD', 'CHARTERED', 'BANK', '-}']
I want to search contiguously the items of list1 in list2 and return the immediate next element of list2 when there's a match.
As you can see, one item of list1 is probably two contiguous item in list2.
For example, the 1st element of list1, 'SETTLEMENT DATE:', There's a match in list2 and I want to return the next element of the match in list2, '20.02.2020'.
I have written my python function accordingly:
def test(items, split_t):
phrases = [w for w in items]
for i, t in enumerate(split_t):
to_match = split_t[i+1: i+1+len(phrases)]
if to_match and all(p == m for p,m in zip(phrases, to_match)):
return [*map(lambda x:split_t[i])]
Which is returning None even when it has matches as you can see. I might be wrong in implementing the *map in the return statement which I'm failing to understand from debugging. Any help is highly appreciated.
One way is:
>>> import re
>>> def test(items, split_t):
... split_t_str = ' '.join(split_t)
... res = {}
... for i in items:
... m = re.search(rf'(?<={i})\s(.*?)\s', split_t_str)
... res[i] = m.group(1)
... return res
...
>>> test(items, split_t)
{'SETTLEMENT DATE:': '20.02.2020', 'CASH ACCOUNT:': '420551901501', 'ISIN:': 'SN0000000019', 'TRADE DATE:': '17.02.2020', 'PRICE CFA': '14,500.4667', 'SECURITY NAME:': 'SONATEL'}
The above:
creates a str from split_t, i.e., split_t_str,
iterates over items using each element to construct a regex for performing a positive lookbehind assertion (see re's docs) against split_t_str,
stores each element as key in a dict, called res, and the corresponding match as value, and
returns the dict
If there is no spaces in "list 2" items. This way you can.
def match(l1, l2):
result = []
string = ' '.join(l2) + ' '
for i in l1:
index = string.find(i)
if index != -1:
result.append(string[index + len(i) + 1:string.find(' ', index + len(i) + 1)])
return result
print(match(items, split_t))
Output:
['20.02.2020', '420551901501', 'SN0000000019', '17.02.2020', '14,500.4667', '420551901501', 'SONATEL']

Replace multiple instances of a sub-string with items in a list

I have a string like below:
e = "how are you how do you how are they how"
My expected output is:
out = "how1 are you how2 do you how3 are they how4"
I'm trying in the following way:
def givs(y,x):
tt = []
va = [i+1 for i in list(range(y.count(x)))]
for i in va:
tt.append(x+str(i))
return tt
ls = givs(e, 'how')
ls = ['how1', 'how2', 'how3', 'how4']
fg = []
for i in e.split(' '):
fg.append(i)
fg = ['how', 'are', 'you', 'how', 'do', 'you', 'how', 'are', 'they', 'how']
For every instance of 'how' in 'fg' I want to replace with items in 'ls' and finally use join function to get the required output.
expected_output = ['how1', 'are', 'you', 'how2', 'do', 'you', 'how3', 'are',
'they', 'how4']
so that I can join the items by:
' '.join(expected_output)
to get:
out = "how1 are you how2 do you how3 are they how4"
You could use itertools.count:
from itertools import count
counter = count(1)
e = "how are you how do you how are they how"
result = ' '.join([w if w != "how" else w + str(next(counter)) for w in e.split()])
print(result)
Output
how1 are you how2 do you how3 are they how4
There is no need to make your code complex, just add a counter and add it to every "how". At the end make the new string.
e = "how are you how do you how are they how"
e_ok = ""
count = 1
for i in e.split():
if i == "how":
i = i+str(count)
count += 1
e_ok += i + " "
print(e_ok)

Python. How do I make a list of small portions of a bigger list?

for word in list6:
if word = "TRUMP":
So, I have a list of every word in a debate transcript. When Trump speaks, it starts with "TRUMP". I need to take his words and put them into a seperate list. If the word in list6 is "TRUMP", then I need to put everything into a list until it says another person's name. He speaks more than once.
I just need help completing this loop.
list6 = ['TRUMP','I','am','good', 'HILLARY','I','am','good','too','TRUMP','But','How?']
person_words = {'TRUMP':[], 'HILLARY':[]}
person_names = person_words.keys()
one_person_onetime_words = []
for word in list6:
if word in person_names:
if len(one_person_onetime_words):
person_words[this_person].append(one_person_onetime_words)
one_person_onetime_words = []
this_person = word
else:
one_person_onetime_words.append(word)
person_words[this_person].append(one_person_onetime_words)
print person_words
Gives
{'HILLARY': [['I', 'am', 'good', 'too']], 'TRUMP': [['I', 'am', 'good'], ['But', 'How?']]}
So, this in a single shot gives all the different talks by all the persons.
As mentioned by you in the comments to your question, if you want to get one person's words only you can use the following:
from copy import copy
list6 = ['TRUMP','I','am','good', 'HILLARY','I','am','good','too','TRUMP','But','How?']
person_words = []
all_persons = ['TRUMP', 'HILLARY']
person_looking_for = 'TRUMP'
filter_out_persons = copy(all_persons)
filter_out_persons.remove(person_looking_for)
person_onetime_words = []
capture_words = False
for word in list6:
if word == person_looking_for:
capture_words = True
if len(person_onetime_words):
person_words.append(person_onetime_words)
person_onetime_words = []
elif word not in filter_out_persons and capture_words:
person_onetime_words.append(word)
else:
capture_words = False
person_words.append(person_onetime_words)
print "{}'s words".format(person_looking_for)
print person_words
That gives
TRUMP's words
[['I', 'am', 'good'], ['But', 'How?']]
And, the following will give a dictionary with words as keys and the value will be a dictionary again with frequency of each person for that word.
import pprint
list6 = ['TRUMP','I','am','good', 'HILLARY','I','am','good','too','TRUMP','But','How?']
person_names = ['TRUMP','HILLARY']
word_frequency = {}
for word in list6:
if word in person_names:
person = word
else:
word = word.lower()
if word in word_frequency:
if person in word_frequency[word]:
word_frequency[word][person] += 1
else:
word_frequency[word][person] = 1
else:
word_frequency[word] = {person: 1}
pprint.pprint(word_frequency)
Gives
{'am': {'HILLARY': 1, 'TRUMP': 1},
'but': {'TRUMP': 1},
'good': {'HILLARY': 1, 'TRUMP': 1},
'how?': {'TRUMP': 1},
'i': {'HILLARY': 1, 'TRUMP': 1},
'too': {'HILLARY': 1}}

Categories