9 jupytext_version: 1.14.5
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
25 def include_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
26 with_letter = [w for w in dictionary if letter in w]
27 without_letter = [w for w in dictionary if letter not in w]
31 a = random.choice(with_letter)
32 b = random.choice(without_letter)
33 finished = ((edit_distance(a, b) <= limit) and
34 not set(a) <= set(b) and
36 return (RiddleClue(word=a, valence=RiddleValence.Include),
37 RiddleClue(word=b, valence=RiddleValence.Exclude))
39 a, b = include_exclude_clue('s')
40 a, b, set(a.word) - set(b.word), edit_distance(a.word, b.word)
44 def include_include_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
45 with_letter = [w for w in dictionary if letter in w]
49 a = random.choice(with_letter)
50 b = random.choice(with_letter)
51 finished = ((a != b) and
52 (edit_distance(a, b) <= limit) and
53 not set(a) <= set(b) and
55 return (RiddleClue(word=a, valence=RiddleValence.Include),
56 RiddleClue(word=b, valence=RiddleValence.Include))
58 a, b = include_include_clue('s')
59 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
63 def exclude_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
64 without_letter = [w for w in dictionary if letter not in w]
68 a = random.choice(without_letter)
69 b = random.choice(without_letter)
70 finished = ((a != b) and
71 (edit_distance(a, b) <= limit) and
72 not set(a) <= set(b) and
74 return (RiddleClue(word=a, valence=RiddleValence.Exclude),
75 RiddleClue(word=b, valence=RiddleValence.Exclude))
77 a, b = exclude_exclude_clue('s')
78 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
82 def random_clue( letter: str
85 , ee_limit: int = 2) -> (RiddleClue, RiddleClue):
86 clue_type = random.choices(['include_exclude', 'include_include', 'exclude_exclude'],
89 if clue_type == 'include_exclude':
90 return include_exclude_clue(letter, limit=ie_limit)
91 elif clue_type =='include_include':
92 return include_include_clue(letter, limit=ii_limit)
94 return exclude_exclude_clue(letter, limit=ee_limit)
98 def random_riddle( word: str
105 ie_limit=ie_limit, ii_limit=ii_limit, ee_limit=ee_limit)
106 for i, l in enumerate(word)}
110 sample_riddle = random_riddle('teacup')
115 solve_riddle(collapse_riddle_clues(sample_riddle))
119 def valid_random_riddle(word: str) -> Riddle:
122 riddle = random_riddle(word)
123 solns = solve_riddle(collapse_riddle_clues(riddle))
124 finished = (len(solns) == 1)
132 for _ in range(1000):
133 w1, c1 = time.perf_counter(), time.process_time()
134 r = valid_random_riddle(random.choice(dictionary))
135 w2, c2 = time.perf_counter(), time.process_time()
137 reports.append({'wall_time': w2 - w1,
139 'riddle_lines': linecount})
140 w_times.append(w2 - w1)
141 c_times.append(c2 - c1)
143 with open('metrics_original.csv', 'w', newline='') as csvfile:
144 fieldnames = list(reports[0].keys())
145 writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
153 def write_include_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
154 line = f"is in {clue_a.word} but not in {clue_b.word}"
159 def write_include_include_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
160 if random.randrange(2) == 0:
161 line = f"is in {clue_a.word} and also in {clue_b.word}"
163 line = f"is in both {clue_a.word} and {clue_b.word}"
168 def write_exclude_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
169 line = f"is neither in {clue_a.word} nor in {clue_b.word}"
174 def write_line(a: RiddleClue, b: RiddleClue) -> str:
175 if a.valence == RiddleValence.Include and b.valence == RiddleValence.Include:
176 return write_include_include_line(a, b)
177 elif a.valence == RiddleValence.Include and b.valence == RiddleValence.Exclude:
178 return write_include_exclude_line(a, b)
179 elif a.valence == RiddleValence.Exclude and b.valence == RiddleValence.Exclude:
180 return write_exclude_exclude_line(a, b)
182 return "illegal line"
186 def write_riddle(riddle: Riddle) -> List[str]:
188 for i, (clue_a, clue_b) in sorted(riddle.items()):
189 pos = reverse_ordinals[i]
190 if i == len(riddle) and random.random() <= 0.3:
191 pos = reverse_ordinals[-1]
192 line = write_line(clue_a, clue_b)
193 full_line = f"My {pos} {line}"
194 output.append(full_line)
203 sample_riddle = valid_random_riddle("elephant")
208 write_riddle(sample_riddle)
212 solve_riddle(collapse_riddle_clues(sample_riddle))
216 with open("generated-riddles.txt", 'w') as file:
222 target = random.choice(dictionary)
223 riddle = valid_random_riddle(target)
224 lines = write_riddle(riddle)
225 file.writelines(l + '\n' for l in lines)
226 file.write(f'Target: {target}\n')