Public » Miscellaneous » Twenty
Clone URL:  
Pushed to one repository · View In Graph Contained in tip

fix a nasty bug where the questions don't, you know, work

Changeset e6822d100bdf

Parent 934ac23a0313

by Profile picture of Benjamin PollackBenjamin Pollack

Changes to 2 files · Browse files at e6822d100bdf Showing diff from parent 934ac23a0313 Diff from another changeset...

Change 1 of 1 Show Entire File brain.py Stacked
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
@@ -1,207 +1,231 @@
-import os -import pickle - -def ask(question): - """ask a question, and return True if the answer yes, False otherwise""" - while True: - print question, - answer = raw_input().strip().lower() - if answer in ('y', 'yes', 'yeah', 'si'): - return True - elif answer in ('n', 'no', 'nope'): - return False - else: - print 'Please type "yes" or "no"' - -class Determiner(object): - """represents a question that helps us narrow down possible answers - - Determiners need to know about their questioner, so they can let - the questioner know how things are going. They also have a - true_question and a false_question property that stores the next - thing to ask if the user says yes/no, respectively. - """ - def __init__(self, questioner, question, true_question, false_question): - self.questioner = questioner - self._question = question - self.true_question = true_question - self.false_question = false_question - - def question(self): - """returns the question as a string""" - return self._question - - def ask(self): - """asks the user on the command line - - You can use Determiner.question() to grab the question text, - and manually call Questioner.advance_yes() or - Questioner.advance_no(), if you want to ask users questions in - other ways. This is here just for convenience. - """ - if ask(self.question()): - self.questioner.advance_yes() - else: - self.questioner.advance_no() - - -class Thing(object): - """represents a concrete thing that might be the right answer - - For example, valid Things might be "a dog", "a cat", "Apollo 11", - and so on. - """ - def __init__(self, questioner, what): - self.questioner = questioner - self.what = what - - def question(self): - """returns the question as a string - - This nicely formats things for you in the form of a question - so you don't have to. - """ - return 'Are you thinking of %s?' % self.what - - def ask(self): - """asks the user on the command line - - You can use Determiner.question() to grab the question text, - and manually call Questioner.mark_failed() or - Questioner.mark_succeeded(), if you want to ask users - questions in other ways. This is here just for convenience. - """ - if ask(self.question()): - self.questioner.mark_succeeded() - else: - self.questioner.mark_failed() - - -class Questioner(object): - """holds all knowledge in the universe as a form of yes/no questions - - Take a look at Thing and Determiner to learn more about how this works. - """ - def __init__(self, initial_question): - self.root = Determiner(self, initial_question, None, None) - - def start(self): - """resets the questioner and starts a new game""" - self.current_question = self.root - self._solved = False - self._failed = False - - def next_question(self): - """returns the next question that you should ask - - This will actually keep returning the same question until you - tell the questioner to continue by calling advance_yes, - advance_no, mark_succeeded, or mark_failed, as appropriate. - """ - return self.current_question - - def advance_yes(self): - """tell the Questioner that his last Determiner was answered yes - - If the last question asked was actually a Thing, use - mark_succeeded instead - """ - self.last_branch = True - self.last_question = self.current_question - self.current_question = self.current_question.true_question - - def advance_no(self): - """tell the Questioner that his last Determiner was answered no - - If the last question asked was actually a Thing, use - mark_failed instead - """ - self.last_branch = False - self.last_question = self.current_question - self.current_question = self.current_question.false_question - - def out_of_ideas(self): - """tell the user if we don't have any idea what they were thinking of""" - return self.current_question is None or self._failed - - def solved(self): - """return True if we're all done""" - return self._solved - - def learn_thing_and_question(self, question, thing): - """learn both a new thing and a question to distinguish it - - We use this when we had the right general idea, but not the - right answer, so that we can distinguish our best guess from - the right answer. You call this when needs_clarification was - True. - """ - true_answer = Thing(self, thing) - false_answer = self.last_question.true_question - new_question = Determiner(self, question, true_answer, false_answer) - if self.last_branch == True: - self.last_question.true_question = new_question - else: - self.last_question.false_question = new_question - - def learn_thing(self, thing): - """learn just a new thing - - You can call this if we just have no more ideas, but we didn't - ever actually guess anything. You call this if - needs_clarification was False. - """ - new_thing = Thing(self, thing) - if self.last_branch == True: - self.last_question.true_question = new_thing - else: - self.last_question.false_question = new_thing - - def needs_clarification(self): - """tell the user whether we need a clarifying question - - This happens when we tried to guess something--i.e., we'd - asked all the questions we thought we had to ask, but we - didn't get to the answer. - """ - return self.current_question is not None - - def mark_succeeded(self): - """tell the Questioner they succeeded - - Once you call this, the Questioner assumes they got it, even - if they didn't, so don't call this unless the user's really - gotten the right answer. - """ - self._solved = True - - def mark_failed(self): - """tell the Questioner they failed - - Once you call this, the Questioner assumes they messed up, - even if they secretly actually really got it. Don't lie. - It's not nice. - """ - self._failed = True - - def best_guess(self): - """return our best guess, if we had one - - This will only return something if we tried to guess a Thing. - Otherwise, it returns None. - """ - if isinstance(self.current_question, Thing): - return self.current_question.what - -def load(path): - """load an existing Questioner from a database""" - if os.path.exists(path): - with open(path, 'rb') as f: - return pickle.load(f) - else: - return Questioner('Does it have four legs?') - -def save(path, questioner): - """save an existing Questioner to a database""" - with open(path, 'wb') as f: - pickle.dump(questioner, f, pickle.HIGHEST_PROTOCOL) +import os +import pickle + +def ask(question): + """ask a question, and return True if the answer yes, False otherwise""" + while True: + print question, + answer = raw_input().strip().lower() + print '' + if answer in ('y', 'yes', 'yeah', 'si'): + return True + elif answer in ('n', 'no', 'nope'): + return False + else: + print 'Please type "yes" or "no"' + +class Determiner(object): + """represents a question that helps us narrow down possible answers + + Determiners need to know about their questioner, so they can let + the questioner know how things are going. They also have a + true_question and a false_question property that stores the next + thing to ask if the user says yes/no, respectively. + """ + def __init__(self, questioner, question, true_question, false_question): + self.questioner = questioner + self._question = question + self.true_question = true_question + self.false_question = false_question + + def question(self): + """returns the question as a string""" + return self._question + + def ask(self): + """asks the user on the command line + + You can use Determiner.question() to grab the question text, + and manually call Questioner.advance_yes() or + Questioner.advance_no(), if you want to ask users questions in + other ways. This is here just for convenience. + """ + if ask(self.question()): + self.questioner.advance_yes() + else: + self.questioner.advance_no() + + +class Thing(object): + """represents a concrete thing that might be the right answer + + For example, valid Things might be "a dog", "a cat", "Apollo 11", + and so on. + """ + def __init__(self, questioner, what): + self.questioner = questioner + self.what = what + + def question(self): + """returns the question as a string + + This nicely formats things for you in the form of a question + so you don't have to. + """ + return 'Are you thinking of %s?' % self.what + + def ask(self): + """asks the user on the command line + + You can use Determiner.question() to grab the question text, + and manually call Questioner.mark_failed() or + Questioner.mark_succeeded(), if you want to ask users + questions in other ways. This is here just for convenience. + """ + if ask(self.question()): + self.questioner.mark_succeeded() + else: + self.questioner.mark_failed() + + +class Questioner(object): + """holds all knowledge in the universe as a form of yes/no questions + + Take a look at Thing and Determiner to learn more about how this works. + """ + def __init__(self, initial_question): + self.root = Determiner(self, initial_question, None, None) + + def start(self): + """resets the questioner and starts a new game""" + self.current_question = self.root + self._solved = False + self._failed = False + + def next_question(self): + """returns the next question that you should ask + + This will actually keep returning the same question until you + tell the questioner to continue by calling advance_yes, + advance_no, mark_succeeded, or mark_failed, as appropriate. + """ + return self.current_question + + def advance_yes(self): + """tell the Questioner that his last Determiner was answered yes + + If the last question asked was actually a Thing, use + mark_succeeded instead + """ + self.last_branch = True + self.last_question = self.current_question + self.current_question = self.current_question.true_question + + def advance_no(self): + """tell the Questioner that his last Determiner was answered no + + If the last question asked was actually a Thing, use + mark_failed instead + """ + self.last_branch = False + self.last_question = self.current_question + self.current_question = self.current_question.false_question + + def out_of_ideas(self): + """tell the user if we don't have any idea what they were thinking of""" + return self.current_question is None or self._failed + + def solved(self): + """return True if we're all done""" + return self._solved + + def learn_thing_and_question(self, question, thing): + """learn both a new thing and a question to distinguish it + + We use this when we had the right general idea, but not the + right answer, so that we can distinguish our best guess from + the right answer. You call this when needs_clarification was + True. + """ + true_answer = Thing(self, thing) + if self.last_branch == True: + false_answer = self.last_question.true_question + new_question = Determiner(self, question, true_answer, false_answer) + self.last_question.true_question = new_question + else: + false_answer = self.last_question.false_question + new_question = Determiner(self, question, true_answer, false_answer) + self.last_question.false_question = new_question + + def learn_thing(self, thing): + """learn just a new thing + + You can call this if we just have no more ideas, but we didn't + ever actually guess anything. You call this if + needs_clarification was False. + """ + new_thing = Thing(self, thing) + if self.last_branch == True: + self.last_question.true_question = new_thing + else: + self.last_question.false_question = new_thing + + def needs_clarification(self): + """tell the user whether we need a clarifying question + + This happens when we tried to guess something--i.e., we'd + asked all the questions we thought we had to ask, but we + didn't get to the answer. + """ + return self.current_question is not None + + def mark_succeeded(self): + """tell the Questioner they succeeded + + Once you call this, the Questioner assumes they got it, even + if they didn't, so don't call this unless the user's really + gotten the right answer. + """ + self._solved = True + + def mark_failed(self): + """tell the Questioner they failed + + Once you call this, the Questioner assumes they messed up, + even if they secretly actually really got it. Don't lie. + It's not nice. + """ + self._failed = True + + def best_guess(self): + """return our best guess, if we had one + + This will only return something if we tried to guess a Thing. + Otherwise, it returns None. + """ + if isinstance(self.current_question, Thing): + return self.current_question.what + + def dump(self): + queue = [self.root] + level = 0 + while queue: + newqueue = [] + for q in queue: + print ' ' * level + q.question() + t, f = q.true_question, q.false_question + if t: + if isinstance(t, Thing): + print ' ' * (level + 1) + 'TRUE: %s' % t.what + else: + newqueue.append(t) + if f: + if isinstance(f, Thing): + print ' ' * (level + 1) + 'FALSE: %s' % f.what + else: + newqueue.append(f) + level += 1 + queue = newqueue + +def load(path): + """load an existing Questioner from a database""" + if os.path.exists(path): + with open(path, 'rb') as f: + return pickle.load(f) + else: + return Questioner('Does it have four legs?') + +def save(path, questioner): + """save an existing Questioner to a database""" + with open(path, 'wb') as f: + pickle.dump(questioner, f, pickle.HIGHEST_PROTOCOL)
Change 1 of 3 Show Entire File twenty.py Stacked
 
1
2
3
 
4
5
6
 
8
9
10
 
11
12
13
 
22
23
24
25
 
 
26
27
28
 
1
2
3
4
5
6
7
 
9
10
11
12
13
14
15
 
24
25
26
 
27
28
29
30
31
@@ -1,6 +1,7 @@
 #!/usr/bin/env python    from brain import load, save +from magic import tell_me_about, take_me_to, image_of    BRAIN_DB = 'brain.db'   @@ -8,6 +9,7 @@
  while True:   print question,   answer = raw_input().strip().lower() + print ''   if answer in ('y', 'yes', 'yeah', 'si'):   return True   elif answer in ('n', 'no', 'nope'): @@ -22,7 +24,8 @@
  question = questioner.next_question()   question.ask()   if questioner.solved(): - print 'I got it!' + print 'I got it!\n' + print tell_me_about(question.what)   if ask('Play again? '):   questioner.start()   else: