X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=riddle_definitions.md;h=1db01f7b1bcc338759f74ee6f8e6a9569b2622e3;hb=1d2814738b8ce6cb2930c22eebeed1c4cb3ed63b;hp=fb025c46a224a986231653ec511512bb1cf6b3b2;hpb=ce34915246926441c163272e09f1343db3fd1955;p=riddle-generator.git diff --git a/riddle_definitions.md b/riddle_definitions.md index fb025c4..1db01f7 100644 --- a/riddle_definitions.md +++ b/riddle_definitions.md @@ -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)]