Tidying and documentation
[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.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 r = random.random()
87 if r <= 0.7:
88 return include_exclude_clue(letter, limit=ie_limit)
89 elif r <= 0.9:
90 return include_include_clue(letter, limit=ii_limit)
91 else:
92 return exclude_exclude_clue(letter, limit=ee_limit)
93 ```
94
95 ```python
96 def random_riddle(word: str, limit: int = 3) -> Riddle:
97 return {i+1 : random_clue(l, ie_limit=limit)
98 for i, l in enumerate(word)}
99 ```
100
101 ```python
102 sample_riddle = random_riddle('sonnet')
103 sample_riddle
104 ```
105
106 ```python
107
108 ```
109
110 ```python
111 sample_riddle = random_riddle('sonnet', limit=4)
112 sample_riddle
113 ```
114
115 ```python
116 sample_riddle
117 ```
118
119 ```python
120 collapse_riddle_clues(sample_riddle)
121 ```
122
123 ```python
124 solve_riddle(collapse_riddle_clues(sample_riddle))
125 ```
126
127 ```python
128 def valid_random_riddle(word: str) -> Riddle:
129 finished = False
130 while not finished:
131 riddle = random_riddle(word)
132 solns = solve_riddle(collapse_riddle_clues(riddle))
133 finished = (len(solns) == 1)
134 return riddle
135 ```
136
137 ```python
138 def write_include_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
139 line = f"is in {clue_a.word} but not in {clue_b.word}"
140 return line
141 ```
142
143 ```python
144 def write_include_include_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
145 line = f"is in {clue_a.word} and also in {clue_b.word}"
146 return line
147 ```
148
149 ```python
150 def write_exclude_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
151 line = f"is neither in {clue_a.word} nor in {clue_b.word}"
152 return line
153 ```
154
155 ```python
156 def write_line(a: RiddleClue, b: RiddleClue) -> str:
157 if a.valence == RiddleValence.Include and b.valence == RiddleValence.Include:
158 return write_include_include_line(a, b)
159 elif a.valence == RiddleValence.Include and b.valence == RiddleValence.Exclude:
160 return write_include_exclude_line(a, b)
161 elif a.valence == RiddleValence.Exclude and b.valence == RiddleValence.Exclude:
162 return write_exclude_exclude_line(a, b)
163 else:
164 return "illegal line"
165 ```
166
167 ```python
168 def write_riddle(riddle: Riddle) -> List[str]:
169 output = []
170 for i, (clue_a, clue_b) in sorted(riddle.items()):
171 pos = reverse_ordinals[i]
172 if i == len(riddle) and random.random() <= 0.3:
173 pos = reverse_ordinals[-1]
174 line = write_line(clue_a, clue_b)
175 full_line = f"My {pos} {line}"
176 output.append(full_line)
177 return output
178 ```
179
180 ```python
181
182 ```
183
184 ```python
185 sample_riddle = valid_random_riddle("elephant")
186 sample_riddle
187 ```
188
189 ```python
190 write_riddle(sample_riddle)
191 ```
192
193 ```python
194 solve_riddle(collapse_riddle_clues(sample_riddle))
195 ```
196
197 ```python
198 with open("generated-riddles.txt", 'w') as file:
199 between = False
200 for _ in range(10):
201 if between:
202 file.write('\n')
203 between = True
204 target = random.choice(dictionary)
205 riddle = valid_random_riddle(target)
206 lines = write_riddle(riddle)
207 file.writelines(l + '\n' for l in lines)
208 file.write(f'Target: {target}\n')
209
210 ```
211
212 ```python
213
214 ```