Related
I'm currently practicing on recursion and growing lists. However, I encountered an error where both "AND" and "NOT IN" functions won't work. It keeps on returning True regardless of the outcome.
Based on the code, this line:
if (a not in routeList) and (b not in routeList):
won't work.
Here's my Input and Output:
You are currently in LGA airport.
Here are the airports
['BIG', 'CDG', 'GGG', 'DEL', 'DOH', 'DSM', 'EWR', 'EYW', 'HND', 'ICN', 'JFK', 'LGA', 'LHR', 'ORD', 'SAN', 'SFO', 'SIN', 'TLV', 'BUD']
-What's your destination? SIN
count: 0
a CDG
routeList [['CDG']]
count: 1
a FFF
routeList [['CDG'], ['FFF']]
count: 2
b CDG
routeList [['CDG'], ['FFF'], ['CDG']]
The last array ['CDG'] should not be included on the current routeList because it already exists. How can I fix this?
#You must return the shortest path in any airports.
#The starting Airport should be in LGA
#List of Airports
airports = ['BIG', 'CDG', 'GGG', 'DEL', 'DOH', 'DSM', 'EWR', 'EYW', 'HND', 'ICN', 'JFK', 'LGA', 'LHR', 'ORD', 'SAN', 'SFO', 'SIN', 'TLV', 'BUD']
#This is the airport routes
routes = [
['BGI', 'LGA'],
['CDG', 'BUD'],
['CDG', 'SIN'],
['DEL', 'CDG'],
['DEL', 'DOH'],
['DSM', 'ORD'],
['EWR', 'HND'],
['EYW', 'LHR'],
['FFF', 'SIN'],
['HND', 'ICN'],
['HND', 'JFK'],
['ICN', 'JFK'],
['JFK', 'LGA'],
['LHR', 'SFO'],
['ORD', 'BGI'],
['SAN', 'EYW'],
['SFO', 'DSM'],
['SFO', 'SAN'],
['SIN', 'CDG'],
['TLV', 'DEL'],
]
startingAirport = 'LGA'
routeList = []
tempList = []
def checkRoute(startPt):
global routes
global routeList
global startingAirport
tempList = []
count1 = 0
for i in routes:
if startPt in i:
a,b = i
if (a not in routeList) and (b not in routeList):# == True:
#if (a,b) not in routeList:
print('count: %d' %count1)
if (a != startPt):# and (a not in routeList):
tempList.append(a)
print('a', a)
elif b != startPt:# and (b not in routeList):
tempList.append(b)
print('b', b)
count1+=1
routeList.append(tempList[:])
print('routeList',routeList)
tempList.clear()
def main():
print(len(routes))
print("You are currently in %s airport.\n" % startingAirport)
print("Here are the airports")
print(airports)
userIn = input("What's your destination? ")
if userIn not in airports:
print("\nThis Airport name is not listed. Please try again")
main()
else:
checkRoute(userIn)
main()
Your problem is that the string 'CDG' does not equal the array ['CDG']
It's a little messy but I trust you can clean it up:
if ([a] not in routeList) and ([b] not in routeList):
count1+=1
print('count: %d' %count1)
if (a != startPt):
tempList.append(a)
print('a', a)
elif b != startPt:
tempList.append(b)
print('b', b)
routeList.append(tempList[:])
print('routeList',routeList)
tempList.clear()
I am trying to write a function that, given a dictionary of restaurants, allows you to randomly pick a restaurant based on your choice of one of the values. For example, if you say you want a bakery then it will only give you bakeries.
I have only worked on the code for choosing the type of restaurant so far, and I am struggling with how to generate a random list. So I am checking for a value and, if it has it, would want to add the key to a list. Does anyone have any suggestions on how to do this?
import random
Restaurants ={
"Eureka": ["American", "$$", "Lunch", "Dinner"],
"Le_Pain": ["Bakery", "$$", "Breakfast", "Lunch", "Dinner"],
"Creme_Bakery": ["Bakery", "$", "Snack"]
}
list=[]
def simple_chooser():
print('Would you like to lock a category or randomize? (randomize, type, price, or meal)')
start= input()
if start=="randomize":
return #completely random
elif start=="type":
print("American, Bakery, Pie, Ice_Cream, Bagels, Asian, Chocolate, Italian, Pizza, Thai, Mexican, Japanese, Acai, Mediterranean, or Boba/Coffee?")
type=input()
for lst in Restaurants.values():
for x in lst:
if x==type:
list.append(x)
return(random.choice(list))
To return completely random restaurant suggestions you need to create a list of all the types first and then you can choose one and return the names of the restaurants.
import random
Restaurants ={
"Eureka": ["American", "$$", "Lunch", "Dinner"],
"Le_Pain": ["Bakery", "$$", "Breakfast", "Lunch", "Dinner"],
"Creme_Bakery": ["Bakery", "$", "Snack"]
}
types = ['American', 'Bakery', 'Pie', 'Ice_Cream', 'Bagels', 'Asian', 'Chocolate', 'Italian',
'Pizza', 'Thai', 'Mexican', 'Japanese', 'Acai', 'Mediterranean','Boba/Coffee']
def simple_chooser():
l=[]
print('Would you like to lock a category or randomize? (randomize, type, price, or meal)')
start= input()
if start=="randomize":
type_random = random.choice(types)
for k,v in Restaurants.items():
if v[0] == type_random:
l.append(k)
elif start=="type":
print("American, Bakery, Pie, Ice_Cream, Bagels, Asian, Chocolate, Italian, Pizza, Thai, Mexican, Japanese, Acai, Mediterranean, or Boba/Coffee?")
type_chosen=input()
for k,v in Restaurants.items():
if v[0] == type_chosen:
l.append(k)
return(random.choice(l))
Also, you don't need to return in if-else statements. Once you have your list of Restaurants you can randomly choose a restaurant and return it.
In your loop, you don't have the restaurant name, as you iterate on the values, you would have need something like
for name, props in Restaurants.items():
if props[0] == type:
list.append(name)
return (random.choice(list)) # wait for the whole list to be constructed
With a better naming (don't use type and list that are builtin methods)
def simple_chooser():
start = input('Would you like to lock a category or randomize? (randomize, type, price, or meal)')
if start == "randomize":
return # completely random
elif start == "type":
restaurant_type = input("American, Bakery, Pie, Ice_Cream, Bagels, Asian, Chocolate, Italian, "
"Pizza, Thai, Mexican, Japanese, Acai, Mediterranean, or Boba/Coffee?")
matching_names = [name for name, props in Restaurants.items() if props[0] == restaurant_type]
return random.choice(matching_names)
You make processing difficult because of the design of your data structures.
Here's an idea which should be easily adapted to future needs.
import random
from operator import contains, eq
Restaurants = [
{'name': 'Eureka', 'type': 'American', 'price': '$$', 'meal': ('Dinner',)},
{'name': 'Le_Pain', 'type': 'Bakery', 'price': '$$', 'meal': ('Lunch', 'Dinner')},
{'name': 'Creme_Bakery', 'type': 'Bakery', 'price': '$', 'meal': ('Snack',)}
]
def get_attr(k):
s = set()
for r in Restaurants:
if isinstance(r[k], tuple):
for t in r[k]:
s.add(t)
else:
s.add(r[k])
return s
def choose_restaurant():
categories = ', '.join(Restaurants[0])
while True:
choice = input(f'Select by category ({categories}) or choose random: ')
if choice == 'random':
return random.choice(Restaurants)
if choice in Restaurants[0]:
choices = get_attr(choice)
if (v := input(f'Select value for {choice} from ({", ".join(choices)}): ')) in choices:
op = contains if isinstance(Restaurants[0][choice], tuple) else eq
return [r for r in Restaurants if op(r[choice], v)]
print('Invalid selection\x07')
print(choose_restaurant())
Restaurants is now a list of dictionaries which is easy to extend. You just need to make sure that each new restaurant has the same structure (keys). Also note that the 'meal' value is a tuple even if there's a single value
I have the following code:
import os
import pprint
file_path = input("Please, enter the path to the file: ")
if os.path.exists(file_path):
worker_dict = {}
k = 1
for line in open(file_path,'r'):
split_line = line.split()
worker = 'worker{}'.format(k)
worker_name = '{}_{}'.format(worker, 'name')
worker_yob = '{}_{}'.format(worker, 'yob')
worker_job = '{}_{}'.format(worker, 'job')
worker_salary = '{}_{}'.format(worker, 'salary')
worker_dict[worker_name] = ' '.join(split_line[0:2])
worker_dict[worker_yob] = ' '.join(split_line[2:3])
worker_dict[worker_job] = ' '.join(split_line[3:4])
worker_dict[worker_salary] = ' '.join(split_line[4:5])
k += 1
else:
print('Error: Invalid file path')
File:
John Snow 1967 CEO 3400$
Adam Brown 1954 engineer 1200$
Output from worker_dict:
{
'worker1_job': 'CEO',
'worker1_name': 'John Snow',
'worker1_salary': '3400$',
'worker1_yob': '1967',
'worker2_job': 'engineer',
'worker2_name': 'Adam Brown',
'worker2_salary': '1200$',
'worker2_yob': '1954',
}
And I want to sort data by worker name and after that by salary. So my idea was to create a separate list with salaries and worker names to sort. But I have problems with filling it, maybe there is a more elegant way to solve my problem?
import os
import pprint
file_path = input("Please, enter the path to the file: ")
if os.path.exists(file_path):
worker_dict = {}
k = 1
with open(file_path,'r') as file:
content=file.read().splitlines()
res=[]
for i in content:
val = i.split()
name = [" ".join([val[0],val[1]]),]#concatenate first name and last name
i=name+val[2:] #prepend name
res.append(i) #append modified value to new list
res.sort(key=lambda x: x[3])#sort by salary
print res
res.sort(key=lambda x: x[0])#sort by name
print res
Output:
[['Adam Brown', '1954', 'engineer', '1200$'], ['John Snow', '1967', 'CEO', '3400$']]
[['Adam Brown', '1954', 'engineer', '1200$'], ['John Snow', '1967', 'CEO', '3400$']]
d = {
'worker1_job': 'CEO',
'worker1_name': 'John Snow',
'worker1_salary': '3400$',
'worker1_yob': '1967',
'worker2_job': 'engineer',
'worker2_name': 'Adam Brown',
'worker2_salary': '1200$',
'worker2_yob': '1954',
}
from itertools import zip_longest
#re-group:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
#re-order:
res = []
for group in list(grouper(d.values(), 4)):
reorder = [1,2,0,3]
res.append([ group[i] for i in reorder])
#sort:
res.sort(key=lambda x: (x[1], x[2]))
output:
[['Adam Brown', '1200$', 'engineer', '1954'],
['John Snow', '3400$', 'CEO', '1967']]
Grouper is defined and explained in itertools. I've grouped your dictionary by records pertaining to each worker, returned it as a reordered list of lists. As lists, I sort them by the name and salary. This is solution is modular: it distinctly groups, re-orders and sorts.
I recommend to store the workers in a different format, for example .csv, then you could use csv.DictReader and put it into a list of dictionaries (this would also allow you to use jobs, names, etc. with more words like "tomb raider").
Note that you have to convert the year of birth and salary to ints or floats to sort them correctly, otherwise they would get sorted lexicographically as in a real world dictionary (book) because they are strings, e.g.:
>>> sorted(['100', '11', '1001'])
['100', '1001', '11']
To sort the list of dicts you can use operator.itemgetter as the key argument of sorted, instead of a lambda function, and just pass the desired key to itemgetter.
The k variable is useless, because it's just the len of the list.
The .csv file:
"name","year of birth","job","salary"
John Snow,1967,CEO,3400$
Adam Brown,1954,engineer,1200$
Lara Croft,1984,tomb raider,5600$
The .py file:
import os
import csv
from operator import itemgetter
from pprint import pprint
file_path = input('Please, enter the path to the file: ')
if os.path.exists(file_path):
with open(file_path, 'r', newline='') as f:
worker_list = list(csv.DictReader(f))
for worker in worker_list:
worker['salary'] = int(worker['salary'].strip('$'))
worker['year of birth'] = int(worker['year of birth'])
pprint(worker_list)
pprint(sorted(worker_list, key=itemgetter('name')))
pprint(sorted(worker_list, key=itemgetter('salary')))
pprint(sorted(worker_list, key=itemgetter('year of birth')))
You still need some error handling, if a int conversion fails, or just let the program crash.
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}}
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'])