4 formats: ipynb,md,py:percent
9 jupytext_version: 1.15.0
11 display_name: Python 3 (ipykernel)
17 from riddle_definitions import *
19 from typing import Dict, Tuple, List, Set
20 from enum import Enum, auto
29 len([w for w in dictionary if 's' in w])
33 len([w for w in dictionary if 's' not in w])
37 dset = set(frozenset(w) for w in dictionary)
38 len(dset), len(dictionary)
42 len([w for w in dset if 's' in w])
46 len([w for w in dset if 's' not in w])
50 sw = random.choice([w for w in dictionary if 's' in w])
55 swrel = [w for w in dictionary if 's' not in w if edit_distance(w, sw) <=3]
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]
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
77 return (RiddleClue(word=a, valence=RiddleValence.Include),
78 RiddleClue(word=b, valence=RiddleValence.Exclude))
80 a, b = include_exclude_clue('s')
81 a, b, set(a.word) - set(b.word), edit_distance(a.word, b.word)
85 def include_include_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
86 with_letter = [w for w in dictionary if letter in w]
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
98 return (RiddleClue(word=a, valence=RiddleValence.Include),
99 RiddleClue(word=b, valence=RiddleValence.Include))
101 a, b = include_include_clue('s')
102 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
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]
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))
122 a, b = exclude_exclude_clue('s')
123 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
127 def random_clue( letter: str
130 , ee_limit: int = 2) -> (RiddleClue, RiddleClue):
131 clue_type = random.choices(['include_exclude', 'include_include', 'exclude_exclude'],
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)
139 return exclude_exclude_clue(letter, limit=ee_limit)
143 def random_riddle( word: str
150 ie_limit=ie_limit, ii_limit=ii_limit, ee_limit=ee_limit)
151 for i, l in enumerate(word)}
155 sample_riddle = random_riddle('teacup')
160 solve_riddle(collapse_riddle_clues(sample_riddle))
164 # write_riddle(sample_riddle)
168 # sample_riddle = random_riddle('sonnet', limit=4)
177 collapse_riddle_clues(sample_riddle)
181 solve_riddle(collapse_riddle_clues(sample_riddle))
185 def valid_random_riddle(word: str) -> Riddle:
188 riddle = random_riddle(word)
189 solns = solve_riddle(collapse_riddle_clues(riddle))
190 finished = (len(solns) == 1)
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)
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)
214 for _ in range(1000):
216 r = valid_random_riddle(random.choice(dictionary))
218 glcounts.append((gencount, linecount))
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)
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}"
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}"
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}"
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)
252 return "illegal line"
256 def write_riddle(riddle: Riddle) -> List[str]:
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)
273 sample_riddle = valid_random_riddle("elephant")
278 write_riddle(sample_riddle)
282 solve_riddle(collapse_riddle_clues(sample_riddle))
286 with open("generated-riddles.txt", 'w') as file:
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')