Created separate library
[riddle-generator.git] / riddle_solver.md
diff --git a/riddle_solver.md b/riddle_solver.md
new file mode 100644 (file)
index 0000000..a9e3064
--- /dev/null
@@ -0,0 +1,160 @@
+---
+jupyter:
+  jupytext:
+    formats: ipynb,md
+    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 *
+
+import re
+from typing import Dict, Tuple, List, Set
+from enum import Enum, auto
+```
+
+```python
+def tokenise(phrase: str) -> List[str]:
+  return [w.lower() for w in re.split(r'\W+', phrase) if w]
+```
+
+```python
+tokenise("My first is in apple, but not in fish.")
+```
+
+```python
+def parse_line(tokens: List[str]) -> Tuple[int, Tuple[RiddleClue, RiddleClue]]:
+  stripped_tokens = [t for t in tokens if t not in stop_words]
+  
+  position_word = [t for t in stripped_tokens if t in ordinals][0]
+  pos = from_ordinal(position_word)
+  
+  first_index, first_word = [(i, t) for i, t in enumerate(stripped_tokens)
+                            if t not in ordinals 
+                            if t not in negative_words][0]
+  second_index, second_word = [(i, t) for i, t in enumerate(stripped_tokens)
+                            if t not in ordinals 
+                            if t not in negative_words][1]
+  neg_indices = [i for i, t in enumerate(stripped_tokens) if t in negative_words]
+  
+  first_clue = None
+  second_clue = None
+  
+  if neg_indices:
+    if neg_indices[0] < first_index:
+      first_clue = RiddleClue(valence = RiddleValence.Exclude,
+                             word = first_word)
+      if len(neg_indices) > 1:
+          second_clue = RiddleClue(valence = RiddleValence.Exclude,
+                             word = second_word)
+    elif neg_indices[0] < second_index:
+      second_clue = RiddleClue(valence = RiddleValence.Exclude,
+                             word = second_word)
+  
+  if first_clue is None:
+    first_clue = RiddleClue(valence = RiddleValence.Include,
+                             word = first_word)
+  
+  if second_clue is None:
+    second_clue = RiddleClue(valence = RiddleValence.Include,
+                             word = second_word)
+
+  return (pos, (first_clue, second_clue))
+```
+
+```python
+e1 = parse_line(tokenise("My first is in apple, but not in pad."))
+e1
+```
+
+```python
+e2 = parse_line(tokenise("My second is in apple and also in banana."))
+e2
+```
+
+```python
+e3 = parse_line(tokenise('My seventh is neither in callus nor in calves'))
+e3
+```
+
+```python
+sample_riddle_text = """My first is in shoat but not in oath
+My second is in orate but not in ratter
+My third is in preposition but not in osteoporosis
+My fourth is in astern but not in taster
+My fifth is in conscientiousness but not in suction
+My sixth is in immorality but not in immorally"""
+
+sample_riddle_lines = {i: elem 
+                       for i, elem in 
+                       [parse_line(tokenise(l)) 
+                        for l in sample_riddle_text.split('\n')]}
+sample_riddle_lines
+```
+
+```python
+sample_riddle = collapse_riddle_clues(sample_riddle_lines)
+sample_riddle
+```
+
+```python
+def parse_riddle(riddle_text: str) -> Riddle:
+  riddle_lines =  {i: elem 
+                  for i, elem in 
+                   [parse_line(tokenise(l)) for l in riddle_text.split('\n')]}
+  return collapse_riddle_clues(riddle_lines)
+```
+
+```python
+solve_riddle(sample_riddle)
+```
+
+```python
+def parse_and_solve_riddle(riddle_text: str) -> List[str]:
+  riddle = parse_riddle(riddle_text)
+  return solve_riddle(riddle)
+```
+
+```python
+sample_riddles = open('sample-riddles.txt').read().split('\n\n')
+sample_riddles
+```
+
+```python
+[parse_and_solve_riddle(r) for r in sample_riddles]
+```
+
+```python
+sample_riddles = open('generated-riddles.txt').read().split('\n\n')
+sample_riddles = [riddle.split('\nTarget: ') for riddle in sample_riddles]
+sample_riddles = [(r, s.strip()) for r, s in sample_riddles]
+sample_riddles
+```
+
+```python
+for r, s in sample_riddles:
+  found_solns = parse_and_solve_riddle(r)
+  correct = len(found_solns) == 1 and found_solns[0] == s
+  print(found_solns, s, correct)
+```
+
+```python
+# [parse_line(tokenise(line)) for line in sample_riddles[4][0]]
+[parse_line(tokenise(line)) for line in sample_riddles[4][0].split('\n')]
+```
+
+```python
+parse_riddle(sample_riddles[4][0])
+```
+
+```python
+
+```