Created separate library
[riddle-generator.git] / riddle_creator.md
diff --git a/riddle_creator.md b/riddle_creator.md
new file mode 100644 (file)
index 0000000..36b939a
--- /dev/null
@@ -0,0 +1,214 @@
+---
+jupyter:
+  jupytext:
+    formats: ipynb,md,py:percent
+    text_representation:
+      extension: .md
+      format_name: markdown
+      format_version: '1.3'
+      jupytext_version: 1.14.5
+  kernelspec:
+    display_name: Python 3 (ipykernel)
+    language: python
+    name: python3
+---
+
+```python
+from riddle_definitions import *
+
+from typing import Dict, Tuple, List, Set
+from enum import Enum, auto
+import random
+```
+
+```python
+def include_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
+  with_letter = [w for w in dictionary if letter in w]
+  without_letter = [w for w in dictionary if letter not in w]
+  
+  finished = False
+  while not finished:
+    a = random.choice(with_letter)
+    b = random.choice(without_letter)
+    finished = ((edit_distance(a, b) <= limit) and
+                not set(a) <= set(b) and 
+                not set(a) >= set(b))
+  return (RiddleClue(word=a, valence=RiddleValence.Include),
+          RiddleClue(word=b, valence=RiddleValence.Exclude))
+
+a, b = include_exclude_clue('s')
+a, b, set(a.word) - set(b.word), edit_distance(a.word, b.word)
+```
+
+```python
+def include_include_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
+  with_letter = [w for w in dictionary if letter in w]
+  
+  finished = False
+  while not finished:
+    a = random.choice(with_letter)
+    b = random.choice(with_letter)
+    finished = ((a != b) and 
+                (edit_distance(a, b) <= limit) and
+                not set(a) <= set(b) and 
+                not set(a) >= set(b))
+  return (RiddleClue(word=a, valence=RiddleValence.Include),
+          RiddleClue(word=b, valence=RiddleValence.Include))
+
+a, b = include_include_clue('s')
+a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
+```
+
+```python
+def exclude_exclude_clue(letter: str, limit: int = 3) -> (RiddleClue, RiddleClue):
+  without_letter = [w for w in dictionary if letter not in w]
+  
+  finished = False
+  while not finished:
+    a = random.choice(without_letter)
+    b = random.choice(without_letter)
+    finished = ((a != b) and 
+                (edit_distance(a, b) <= limit) and
+                not set(a) <= set(b) and
+                not set(a) >= set(b))                
+  return (RiddleClue(word=a, valence=RiddleValence.Exclude),
+          RiddleClue(word=b, valence=RiddleValence.Exclude))
+
+a, b = exclude_exclude_clue('s')
+a, b, set(a.word) | set(b.word), edit_distance(a.word, b.word)
+```
+
+```python
+def random_clue( letter: str
+               , ie_limit: int = 3
+               , ii_limit: int = 2
+               , ee_limit: int = 2) -> (RiddleClue, RiddleClue):
+  r = random.random()
+  if r <= 0.7:
+    return include_exclude_clue(letter, limit=ie_limit)
+  elif r <= 0.9:
+    return include_include_clue(letter, limit=ii_limit)
+  else:
+    return exclude_exclude_clue(letter, limit=ee_limit)
+```
+
+```python
+def random_riddle(word: str, limit: int = 3) -> Riddle:
+  return {i+1 : random_clue(l, ie_limit=limit)
+          for i, l in enumerate(word)}  
+```
+
+```python
+sample_riddle = random_riddle('sonnet')
+sample_riddle
+```
+
+```python
+
+```
+
+```python
+sample_riddle = random_riddle('sonnet', limit=4)
+sample_riddle
+```
+
+```python
+sample_riddle
+```
+
+```python
+collapse_riddle_clues(sample_riddle)
+```
+
+```python
+solve_riddle(collapse_riddle_clues(sample_riddle))
+```
+
+```python
+def valid_random_riddle(word: str) -> Riddle:
+  finished = False
+  while not finished:
+    riddle = random_riddle(word)
+    solns = solve_riddle(collapse_riddle_clues(riddle))
+    finished = (len(solns) == 1)
+  return riddle
+```
+
+```python
+def write_include_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
+  line = f"is in {clue_a.word} but not in {clue_b.word}"
+  return line
+```
+
+```python
+def write_include_include_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
+  line = f"is in {clue_a.word} and also in {clue_b.word}"
+  return line
+```
+
+```python
+def write_exclude_exclude_line(clue_a: RiddleClue, clue_b: RiddleClue) -> str:
+  line = f"is neither in {clue_a.word} nor in {clue_b.word}"
+  return line
+```
+
+```python
+def write_line(a: RiddleClue, b: RiddleClue) -> str:
+  if a.valence == RiddleValence.Include and b.valence == RiddleValence.Include:
+    return write_include_include_line(a, b)
+  elif a.valence == RiddleValence.Include and b.valence == RiddleValence.Exclude:
+    return write_include_exclude_line(a, b)
+  elif a.valence == RiddleValence.Exclude and b.valence == RiddleValence.Exclude:
+    return write_exclude_exclude_line(a, b)
+  else:
+    return "illegal line"
+```
+
+```python
+def write_riddle(riddle: Riddle) -> List[str]:
+  output = []
+  for i, (clue_a, clue_b) in sorted(riddle.items()):
+    pos = reverse_ordinals[i]
+    if i == len(riddle) and random.random() <= 0.3:
+      pos = reverse_ordinals[-1]
+    line = write_line(clue_a, clue_b)
+    full_line = f"My {pos} {line}"
+    output.append(full_line)
+  return output  
+```
+
+```python
+
+```
+
+```python
+sample_riddle = valid_random_riddle("elephant")
+sample_riddle
+```
+
+```python
+write_riddle(sample_riddle)
+```
+
+```python
+solve_riddle(collapse_riddle_clues(sample_riddle))
+```
+
+```python
+with open("generated-riddles.txt", 'w') as file:
+  between = False
+  for _ in range(10):
+    if between:
+      file.write('\n')
+    between = True
+    target = random.choice(dictionary)
+    riddle = valid_random_riddle(target)
+    lines = write_riddle(riddle)
+    file.writelines(l + '\n' for l in lines)
+    file.write(f'Target: {target}\n')
+                  
+```
+
+```python
+
+```