-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patheinstein-problem.py
155 lines (119 loc) · 5.07 KB
/
einstein-problem.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
'''
author: Jacob Egner
date: 2015-07-30
island: scientific expedition
puzzle URLs:
http://www.checkio.org/mission/einstein-problem/
https://github.com/Bryukh-Checkio-Tasks/checkio-mission-einstein-problem
for latest versions of my solutions, see my checkio solution github repo:
https://github.com/jmegner/CheckioPuzzles
'''
import collections
import copy
import itertools
COLORS = set(['blue', 'green', 'red', 'white', 'yellow'])
PETS = set(['cat', 'bird', 'dog', 'fish', 'horse'])
BEVERAGES = set(['beer', 'coffee', 'milk', 'tea', 'water'])
CIGARETTES = set([
'Rothmans', 'Dunhill', 'Pall Mall', 'Winfield', 'Marlboro'])
NATIONALITY = set(['Brit', 'Dane', 'German', 'Norwegian', 'Swede'])
NUMBERS = set(['1', '2', '3', '4', '5'])
QUESTIONS = set([
"number", "color", "nationality", "beverage", "cigarettes", "pet"])
CATEGORIES = collections.OrderedDict([
('number', NUMBERS),
('color', COLORS),
('nationality', NATIONALITY),
('beverage', BEVERAGES),
('cigarettes', CIGARETTES),
('pet', PETS),
])
def answer(relations, question):
persons = relationsToPersons(relations)
mergePartialPersons(persons)
fillInMissingTraits(persons)
questionTrait, questionCategory = question.split('-')
for person in persons:
if questionTrait in person.values():
return person[questionCategory]
return "unknown"
def relationsToPersons(relations):
persons = []
for traitPair in relations:
newPerson = dict(
(traitToCategory(trait), trait)
for trait in traitPair.split('-')
)
matchingPersons = []
nextGeneration = []
for person in persons:
if set(newPerson.values()) & set(person.values()):
newPerson.update(person)
else:
nextGeneration.append(person)
nextGeneration.append(newPerson)
persons = nextGeneration
return persons
def traitToCategory(trait):
for category, traits in CATEGORIES.items():
if trait in traits:
return category
def mergePartialPersons(persons):
mergedPerson = True # will later become None and person-dict
while mergedPerson:
mergedPerson = None
oldPersons = []
for person1Idx, person1 in enumerate(persons):
if len(person1) == len(CATEGORIES):
continue
for person2 in persons[person1Idx + 1:]:
if len(person2) == len(CATEGORIES):
continue
# if categories do not overlap
if not(set(person1.keys()) & set(person2.keys())):
mergedPerson = person1.copy()
mergedPerson.update(person2)
oldPersons.append(person1)
oldPersons.append(person2)
break
if mergedPerson:
break
if mergedPerson:
for oldPerson in oldPersons:
persons.remove(oldPerson)
persons.append(mergedPerson)
def fillInMissingTraits(persons):
categoryToMissingTraits = copy.deepcopy(CATEGORIES)
for person in persons:
for category, trait in person.items():
categoryToMissingTraits[category].discard(trait)
for person in persons:
if len(person) < len(CATEGORIES):
for category, missingTraits in categoryToMissingTraits.items():
if missingTraits and category not in person:
person[category] = missingTraits.pop()
if __name__ == '__main__':
assert answer(('Norwegian-Dunhill', 'Marlboro-blue', 'Brit-3',
'German-coffee', 'beer-white', 'cat-water',
'horse-2', 'milk-3', '4-Rothmans',
'dog-Swede', 'Norwegian-1', 'horse-Marlboro',
'bird-Brit', '4-green', 'Winfield-beer',
'Dane-blue', '5-dog', 'blue-horse',
'yellow-cat', 'Winfield-Swede', 'tea-Marlboro'),
'fish-color') == 'green' # What is the color of the house where the Fish lives?
assert answer(('Norwegian-Dunhill', 'Marlboro-blue', 'Brit-3',
'German-coffee', 'beer-white', 'cat-water',
'horse-2', 'milk-3', '4-Rothmans',
'dog-Swede', 'Norwegian-1', 'horse-Marlboro',
'bird-Brit', '4-green', 'Winfield-beer',
'Dane-blue', '5-dog', 'blue-horse',
'yellow-cat', 'Winfield-Swede', 'tea-Marlboro'),
'tea-number') == '2' # What is the number of the house where tea is favorite beverage?
assert answer(('Norwegian-Dunhill', 'Marlboro-blue', 'Brit-3',
'German-coffee', 'beer-white', 'cat-water',
'horse-2', 'milk-3', '4-Rothmans',
'dog-Swede', 'Norwegian-1', 'horse-Marlboro',
'bird-Brit', '4-green', 'Winfield-beer',
'Dane-blue', '5-dog', 'blue-horse',
'yellow-cat', 'Winfield-Swede', 'tea-Marlboro'),
'Norwegian-beverage') == 'water' # What is the favorite beverage of the Norwegian man?