Tidying and documentation
authorNeil Smith <NeilNjae@users.noreply.github.com>
Thu, 10 Aug 2023 12:01:02 +0000 (13:01 +0100)
committerNeil Smith <NeilNjae@users.noreply.github.com>
Thu, 10 Aug 2023 12:01:02 +0000 (13:01 +0100)
riddle_definitions.md
riddle_solver.md

index fb025c46a224a986231653ec511512bb1cf6b3b2..402fd949012cd5aa2de4a9c13acf8f41f86cde4c 100644 (file)
@@ -15,6 +15,8 @@ jupyter:
 
 # Definitions generally useful for the riddle solver
 
+While this file is here as a Markdown file, it's intended that Jupytext will save this file as a "percent" Python file, so that it can be imported by other notebooks here.
+
 ```python
 import unicodedata
 import re
@@ -65,6 +67,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 +78,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]
 ```
 
@@ -114,7 +126,9 @@ def edit_distance(s: str, t: str) -> int:
 ```
 
 ```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 +148,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 +163,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 +175,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)]    
index a9e3064dd36242c65fd1b04a11d203e3143ba3d9..67b62988b141f0df6fddc3d05a046aaff07b198f 100644 (file)
@@ -37,12 +37,13 @@ def parse_line(tokens: List[str]) -> Tuple[int, Tuple[RiddleClue, RiddleClue]]:
   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)
+  indexed_words = [(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]
+                            if t not in negative_words]
+  
+  first_index, first_word = indexed_words[0]
+  second_index, second_word = indexed_words[1]
+  
   neg_indices = [i for i, t in enumerate(stripped_tokens) if t in negative_words]
   
   first_clue = None
@@ -107,10 +108,10 @@ 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)
+  return {i: elem 
+          for i, elem in 
+            [parse_line(tokenise(l)) 
+             for l in riddle_text.split('\n')]}
 ```
 
 ```python
@@ -120,7 +121,8 @@ solve_riddle(sample_riddle)
 ```python
 def parse_and_solve_riddle(riddle_text: str) -> List[str]:
   riddle = parse_riddle(riddle_text)
-  return solve_riddle(riddle)
+  elems = collapse_riddle_clues(riddle)
+  return solve_riddle(elems)
 ```
 
 ```python