Working on blog posts
[riddle-generator.git] / riddle_creator.md
1 ---
2 jupyter:
3 jupytext:
4 formats: ipynb,md,py:percent
5 text_representation:
6 extension: .md
7 format_name: markdown
8 format_version: '1.3'
9 jupytext_version: 1.15.0
10 kernelspec:
11 display_name: Python 3 (ipykernel)
12 language: python
13 name: python3
14 ---
15
16 ```python
17 from riddle_definitions import *
18
19 from typing import Dict, Tuple, List, Set
20 from enum import Enum, auto
21 import random
22 ```
23
24 ```python
25 gencount = 0
26 ```
27
28 ```python
29 len([w for w in dictionary if 's' in w])
30 ```
31
32 ```python
33 len([w for w in dictionary if 's' not in w])
34 ```
35
36 ```python
37 dset = set(frozenset(w) for w in dictionary)
38 len(dset), len(dictionary)
39 ```
40
41 ```python
42 len([w for w in dset if 's' in w])
43 ```
44
45 ```python
46 len([w for w in dset if 's' not in w])
47 ```
48
49 ```python
50 sw = random.choice([w for w in dictionary if 's' in w])
51 sw
52 ```
53
54 ```python
55 swrel = [w for w in dictionary if 's' not in w if edit_distance(w, sw) <=3]
56 len(swrel)
57 ```
58
59 ```python
60 swrel
61 ```
62
63 ```python
64 def include_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
65 with_letter = [w for w in dictionary if letter in w]
66 without_letter = [w for w in dictionary if letter not in w]
67
68 finished = False
69 while not finished:
70 global gencount
71 gencount +=1
72 a = random.choice(with_letter)
73 b = random.choice(without_letter)
74 finished = ((edit_distance(a, b) <= limit) and
75 not set(a) <= set(b) and
76 not set(a) >= set(b))
77 return (RiddleClue(word=a, valence=RiddleValence.Include),
78 RiddleClue(word=b, valence=RiddleValence.Exclude))
79
80 a, b = include_exclude_clue('s')
81 a, b, set(a.word) - set(b.word), edit_distance(a.word, b.word)
82 ```
83
84 ```python
85 def include_include_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
86 with_letter = [w for w in dictionary if letter in w]
87
88 finished = False
89 while not finished:
90 global gencount
91 gencount +=1
92 a = random.choice(with_letter)
93 b = random.choice(with_letter)
94 finished = ((a != b) and
95 (edit_distance(a, b) <= limit) and
96 not set(a) <= set(b) and
97 not set(a) >= set(b))
98 return (RiddleClue(word=a, valence=RiddleValence.Include),
99 RiddleClue(word=b, valence=RiddleValence.Include))
100
101 a, b = include_include_clue('s')
102 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
103 ```
104
105 ```python
106 def exclude_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
107 without_letter = [w for w in dictionary if letter not in w]
108
109 finished = False
110 while not finished:
111 global gencount
112 gencount +=1
113 a = random.choice(without_letter)
114 b = random.choice(without_letter)
115 finished = ((a != b) and
116 (edit_distance(a, b) <= limit) and
117 not set(a) <= set(b) and
118 not set(a) >= set(b))
119 return (RiddleClue(word=a, valence=RiddleValence.Exclude),
120 RiddleClue(word=b, valence=RiddleValence.Exclude))
121
122 a, b = exclude_exclude_clue('s')
123 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
124 ```
125
126 ```python
127 def random_clue( letter: str
128 , ie_limit: int = 3
129 , ii_limit: int = 2
130 , ee_limit: int = 2) -> (RiddleClue, RiddleClue):
131 clue_type = random.choices(['include_exclude', 'include_include', 'exclude_exclude'],
132 weights=[7, 2, 1],
133 k=1)[0]
134 if clue_type == 'include_exclude':
135 return include_exclude_clue(letter, limit=ie_limit)
136 elif clue_type =='include_include':
137 return include_include_clue(letter, limit=ii_limit)
138 else:
139 return exclude_exclude_clue(letter, limit=ee_limit)
140 ```
141
142 ```python
143 def random_riddle( word: str
144 , ie_limit: int = 3
145 , ii_limit: int = 2
146 , ee_limit: int = 2
147 ) -> Riddle:
148 return {i+1 :
149 random_clue(l,
150 ie_limit=ie_limit, ii_limit=ii_limit, ee_limit=ee_limit)
151 for i, l in enumerate(word)}
152 ```
153
154 ```python
155 sample_riddle = random_riddle('teacup')
156 sample_riddle
157 ```
158
159 ```python
160 solve_riddle(collapse_riddle_clues(sample_riddle))
161 ```
162
163 ```python
164 # write_riddle(sample_riddle)
165 ```
166
167 ```python
168 # sample_riddle = random_riddle('sonnet', limit=4)
169 # sample_riddle
170 ```
171
172 ```python
173 sample_riddle
174 ```
175
176 ```python
177 collapse_riddle_clues(sample_riddle)
178 ```
179
180 ```python
181 solve_riddle(collapse_riddle_clues(sample_riddle))
182 ```
183
184 ```python
185 def valid_random_riddle(word: str) -> Riddle:
186 finished = False
187 while not finished:
188 riddle = random_riddle(word)
189 solns = solve_riddle(collapse_riddle_clues(riddle))
190 finished = (len(solns) == 1)
191 return riddle
192 ```
193
194 ```python
195 # import time
196 # w_times = []
197 # c_times = []
198 # for _ in range(1000):
199 # w1, c1 = time.perf_counter(), time.process_time()
200 # valid_random_riddle(random.choice(dictionary))
201 # w2, c2 = time.perf_counter(), time.process_time()
202 # w_times.append(w2 - w1)
203 # c_times.append(c2 - c1)
204
205 # with open('cpu_times.txt', 'w') as f:
206 # f.writelines(f'{t}\n' for t in c_times)
207 # with open('wall_times.txt', 'w') as f:
208 # f.writelines(f'{t}\n' for t in w_times)
209
210 ```
211
212 ```python
213 glcounts = []
214 for _ in range(1000):
215 gencount = 0
216 r = valid_random_riddle(random.choice(dictionary))
217 linecount = len(r)
218 glcounts.append((gencount, linecount))
219
220 with open('linecounts.txt', 'w') as f:
221 f.write('"Lines generated","Lines in riddle"\n')
222 f.writelines(f'{g},{l}\n' for g, l in glcounts)
223 ```
224
225 ```python
226 def write_include_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
227 line = f"is in {clue_a.word} but not in {clue_b.word}"
228 return line
229 ```
230
231 ```python
232 def write_include_include_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
233 line = f"is in {clue_a.word} and also in {clue_b.word}"
234 return line
235 ```
236
237 ```python
238 def write_exclude_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
239 line = f"is neither in {clue_a.word} nor in {clue_b.word}"
240 return line
241 ```
242
243 ```python
244 def write_line(a: RiddleClue, b: RiddleClue) -> str:
245 if a.valence == RiddleValence.Include and b.valence == RiddleValence.Include:
246 return write_include_include_line(a, b)
247 elif a.valence == RiddleValence.Include and b.valence == RiddleValence.Exclude:
248 return write_include_exclude_line(a, b)
249 elif a.valence == RiddleValence.Exclude and b.valence == RiddleValence.Exclude:
250 return write_exclude_exclude_line(a, b)
251 else:
252 return "illegal line"
253 ```
254
255 ```python
256 def write_riddle(riddle: Riddle) -> List[str]:
257 output = []
258 for i, (clue_a, clue_b) in sorted(riddle.items()):
259 pos = reverse_ordinals[i]
260 if i == len(riddle) and random.random() <= 0.3:
261 pos = reverse_ordinals[-1]
262 line = write_line(clue_a, clue_b)
263 full_line = f"My {pos} {line}"
264 output.append(full_line)
265 return output
266 ```
267
268 ```python
269
270 ```
271
272 ```python
273 sample_riddle = valid_random_riddle("elephant")
274 sample_riddle
275 ```
276
277 ```python
278 write_riddle(sample_riddle)
279 ```
280
281 ```python
282 solve_riddle(collapse_riddle_clues(sample_riddle))
283 ```
284
285 ```python
286 with open("generated-riddles.txt", 'w') as file:
287 between = False
288 for _ in range(10):
289 if between:
290 file.write('\n')
291 between = True
292 target = random.choice(dictionary)
293 riddle = valid_random_riddle(target)
294 lines = write_riddle(riddle)
295 file.writelines(l + '\n' for l in lines)
296 file.write(f'Target: {target}\n')
297
298 ```
299
300 ```python
301
302 ```