Removed neighbour generation out of the core library
[riddle-generator.git] / riddle_definitions.md
index fb025c46a224a986231653ec511512bb1cf6b3b2..1db01f7b1bcc338759f74ee6f8e6a9569b2622e3 100644 (file)
@@ -13,8 +13,6 @@ jupyter:
     name: python3
 ---
 
-# Definitions generally useful for the riddle solver
-
 ```python
 import unicodedata
 import re
@@ -26,8 +24,8 @@ import random
 ```
 
 ```python
-stop_words = set('my is in within lies and also always you will find the found'.split())
-negative_words = set('but not never neither nor'.split())
+stop_words = set('my is in within lies and also always you will find the found but'.split())
+negative_words = set('not never neither nor'.split())
 ```
 
 ```python
@@ -65,6 +63,7 @@ dictionary : List[str] = [unicodedata.normalize('NFKD', w.strip()).\
               if w.strip().islower()
               if w.strip().isalpha()
               if len(w.strip()) >= 5
+              if len(w.strip()) <= 12
               if w not in stop_words
               if w not in negative_words
               if w not in ordinals
@@ -75,20 +74,29 @@ Some types that will be used throughout the library
 
 ```python
 class RiddleValence(Enum):
+  """Does this part of the riddle include or exclude letters?"""
   Include = auto()
   Exclude = auto()
 
 @dataclass
 class RiddleClue:
+  """A half line of a riddle, like 'is in dreams' or 'not in octet'"""
   valence : RiddleValence
   word : str
   
 @dataclass
 class RiddleElement:
+  """A representation of the constraints that come from a whole line of 
+  a riddle"""
   valence : RiddleValence
   letters : Set[str]
 
+# A riddle that's been read and parsed. 
+# Note that the numbering is one-based, as per the numbers in the riddle text
 Riddle = Dict[int, Tuple[RiddleClue, RiddleClue]]
+
+# A riddle that's been processed ready for solving
+# Note that the numbering is one-based, as per the numbers in the riddle text
 RiddleElems =  Dict[int, RiddleElement]
 ```
 
@@ -99,22 +107,24 @@ def edit_distance(s: str, t: str) -> int:
     return len(t)
   if t == "":
     return len(s)
-  if s[-1] == t[-1]:
+  if s[0] == t[0]:
     cost = 0
   else:
     cost = 1
        
   res = min(
-    [ edit_distance(s[:-1], t)+1
-    , edit_distance(s, t[:-1])+1
-    , edit_distance(s[:-1], t[:-1]) + cost
+    [ edit_distance(s[1:], t) + 1
+    , edit_distance(s, t[1:]) + 1
+    , edit_distance(s[1:], t[1:]) + cost
     ])
 
   return res
 ```
 
 ```python
-def collapse_riddle_clues(elems : Dict[int, Tuple[RiddleClue, RiddleClue]]) -> RiddleElems:
+def collapse_riddle_clues(elems : Riddle) -> RiddleElems:
+  """Combine the two parts of a riddle line into one element for solving.
+  This takes account of the valence of the two parts."""
   def combine_clues(a: RiddleClue, b: RiddleClue) -> RiddleElement:
     if a.valence == b.valence:
       if a.valence == RiddleValence.Include:
@@ -134,12 +144,11 @@ def collapse_riddle_clues(elems : Dict[int, Tuple[RiddleClue, RiddleClue]]) -> R
   return {i: combine_clues(a, b) for i, (a, b) in elems.items()}
 ```
 
-```python
-
-```
-
 ```python
 def matches_element(pos: int, elem: RiddleElement, word: str) -> bool:
+  """Does this element match this position of the the word?
+  Note that positions are one-based, as in the numbering system of the 
+  puzzle."""
   if len(word) < pos:
     return False
   if elem.valence == RiddleValence.Include:
@@ -150,6 +159,7 @@ def matches_element(pos: int, elem: RiddleElement, word: str) -> bool:
 
 ```python
 def matches_all_elements(riddle: RiddleElems, word: str) -> bool:
+  """Do all the elements of a riddle match the appropriate parts of a word?"""
   if -1 in riddle:
     last_elem = riddle[-1]
     new_riddle = {p: e for p, e in riddle.items() if p != -1}
@@ -161,6 +171,7 @@ def matches_all_elements(riddle: RiddleElems, word: str) -> bool:
 
 ```python
 def solve_riddle(riddle: RiddleElems) -> List[str]:
+  """Find all words that match this riddle"""
   return [w for w in dictionary 
           if len(w) == len(riddle)
           if matches_all_elements(riddle, w)]