Removed neighbour generation out of the core library
[riddle-generator.git] / riddle_creator.md
1 ---
2 jupyter:
3 jupytext:
4 formats: ipynb,md
5 text_representation:
6 extension: .md
7 format_name: markdown
8 format_version: '1.3'
9 jupytext_version: 1.14.5
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 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]
28
29 finished = False
30 while not finished:
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
35 not set(a) >= set(b))
36 return (RiddleClue(word=a, valence=RiddleValence.Include),
37 RiddleClue(word=b, valence=RiddleValence.Exclude))
38
39 a, b = include_exclude_clue('s')
40 a, b, set(a.word) - set(b.word), edit_distance(a.word, b.word)
41 ```
42
43 ```python
44 def include_include_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
45 with_letter = [w for w in dictionary if letter in w]
46
47 finished = False
48 while not finished:
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
54 not set(a) >= set(b))
55 return (RiddleClue(word=a, valence=RiddleValence.Include),
56 RiddleClue(word=b, valence=RiddleValence.Include))
57
58 a, b = include_include_clue('s')
59 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
60 ```
61
62 ```python
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]
65
66 finished = False
67 while not finished:
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
73 not set(a) >= set(b))
74 return (RiddleClue(word=a, valence=RiddleValence.Exclude),
75 RiddleClue(word=b, valence=RiddleValence.Exclude))
76
77 a, b = exclude_exclude_clue('s')
78 a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
79 ```
80
81 ```python
82 def random_clue( letter: str
83 , ie_limit: int = 3
84 , ii_limit: int = 2
85 , ee_limit: int = 2) -> (RiddleClue, RiddleClue):
86 clue_type = random.choices(['include_exclude', 'include_include', 'exclude_exclude'],
87 weights=[7, 2, 1],
88 k=1)[0]
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)
93 else:
94 return exclude_exclude_clue(letter, limit=ee_limit)
95 ```
96
97 ```python
98 def random_riddle( word: str
99 , ie_limit: int = 3
100 , ii_limit: int = 2
101 , ee_limit: int = 2
102 ) -> Riddle:
103 return {i+1 :
104 random_clue(l,
105 ie_limit=ie_limit, ii_limit=ii_limit, ee_limit=ee_limit)
106 for i, l in enumerate(word)}
107 ```
108
109 ```python
110 sample_riddle = random_riddle('teacup')
111 sample_riddle
112 ```
113
114 ```python
115 solve_riddle(collapse_riddle_clues(sample_riddle))
116 ```
117
118 ```python
119 def valid_random_riddle(word: str) -> Riddle:
120 finished = False
121 while not finished:
122 riddle = random_riddle(word)
123 solns = solve_riddle(collapse_riddle_clues(riddle))
124 finished = (len(solns) == 1)
125 return riddle
126 ```
127
128 ```python
129 import time
130 import csv
131 reports = []
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()
136 linecount = len(r)
137 reports.append({'wall_time': w2 - w1,
138 'cpu_time': c2 - c1,
139 'riddle_lines': linecount})
140 w_times.append(w2 - w1)
141 c_times.append(c2 - c1)
142
143 with open('metrics_original.csv', 'w', newline='') as csvfile:
144 fieldnames = list(reports[0].keys())
145 writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
146
147 writer.writeheader()
148 for r in reports:
149 writer.writerow(r)
150 ```
151
152 ```python
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}"
155 return line
156 ```
157
158 ```python
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}"
162 else:
163 line = f"is in both {clue_a.word} and {clue_b.word}"
164 return line
165 ```
166
167 ```python
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}"
170 return line
171 ```
172
173 ```python
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)
181 else:
182 return "illegal line"
183 ```
184
185 ```python
186 def write_riddle(riddle: Riddle) -> List[str]:
187 output = []
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)
195 return output
196 ```
197
198 ```python
199
200 ```
201
202 ```python
203 sample_riddle = valid_random_riddle("riddle")
204 sample_riddle
205 ```
206
207 ```python
208 write_riddle(sample_riddle)
209 ```
210
211 ```python
212 solve_riddle(collapse_riddle_clues(sample_riddle))
213 ```
214
215 ```python
216 with open("generated-riddles.txt", 'w') as file:
217 between = False
218 for _ in range(10):
219 if between:
220 file.write('\n')
221 between = True
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')
227
228 ```
229
230 ```python
231
232 ```