From ae3490f47898656ed34205eaf7add458dca33361 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <jmm@yavook.de>
Date: Sun, 20 Aug 2023 11:41:07 +0000
Subject: [PATCH] make helpers operate on seqs; documentation

---
 pigeon_magnet_solver/board.py   | 10 +++++++---
 pigeon_magnet_solver/helpers.py | 23 ++++++++++++++---------
 tests/test_helpers.py           | 23 ++++++++++++-----------
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/pigeon_magnet_solver/board.py b/pigeon_magnet_solver/board.py
index e3c084a..355037e 100644
--- a/pigeon_magnet_solver/board.py
+++ b/pigeon_magnet_solver/board.py
@@ -1,4 +1,5 @@
 from dataclasses import dataclass
+from typing import Self
 
 from .helpers import rotate_r
 
@@ -10,7 +11,7 @@ class Board:
 
     @classmethod
     @property
-    def default_puzzle(cls) -> "Board":
+    def default_puzzle(cls) -> Self:
         return cls(
             rows=["011", "011", "100", "x1x"],
             buttons=(3, 4, 5, 7),
@@ -98,6 +99,7 @@ class Board:
         row, col = index // self.width, index % self.width
         assert self.rows[row][col] == "1", f"{index} is not clickable!"
 
+        # get neighbor positions
         nb_rc = [
             (row - 1, col),
             (row, col + 1),
@@ -105,7 +107,9 @@ class Board:
             (row, col - 1),
         ]
 
-        nb_str = "".join(self[*rc] for rc in nb_rc)
+        # rotate neighbors
+        nb_rot = rotate_r([self[rc] for rc in nb_rc])
 
-        for rc, val in zip(nb_rc, rotate_r(nb_str)):
+        # set new neighbors
+        for rc, val in zip(nb_rc, nb_rot):
             self[rc] = val
diff --git a/pigeon_magnet_solver/helpers.py b/pigeon_magnet_solver/helpers.py
index d868189..4149b72 100644
--- a/pigeon_magnet_solver/helpers.py
+++ b/pigeon_magnet_solver/helpers.py
@@ -1,8 +1,13 @@
-def _rotate_r(__s: str) -> str:
-    return __s[-1] + __s[0:-1]
+from typing import Iterable, TypeVar
+
+T = TypeVar("T")
 
 
-def _valid_rotate(__s: str, __c: str) -> bool:
+def _rotate_r(__s: list[T]) -> list[T]:
+    return [__s[-1]] + __s[0:-1]
+
+
+def _valid_rotate(__s: Iterable[str], __c: Iterable[str]) -> bool:
     for sc, cc in zip(__s, __c):
         # can never rotate a "1" onto an "x"
         if sc == "x" and cc == "1":
@@ -11,23 +16,23 @@ def _valid_rotate(__s: str, __c: str) -> bool:
     return True
 
 
-def _fix_exes(__s: str, __c: str) -> str:
-    result = ""
+def _fix_exes(__s: Iterable[str], __c: Iterable[str]) -> list[str]:
+    result = []
 
     for sc, cc in zip(__s, __c):
         if sc == "x":
-            result += "x"
+            result.append("x")
 
         elif cc == "x":
-            result += "0"
+            result.append("0")
 
         else:
-            result += cc
+            result.append(cc)
 
     return result
 
 
-def rotate_r(__s: str) -> str:
+def rotate_r(__s: list[str]) -> list[str]:
     result = _rotate_r(__s)
 
     while not _valid_rotate(__s, result):
diff --git a/tests/test_helpers.py b/tests/test_helpers.py
index 8fe75c9..87ef134 100644
--- a/tests/test_helpers.py
+++ b/tests/test_helpers.py
@@ -1,17 +1,18 @@
-from pigeon_magnet_solver import helpers
+from pigeon_magnet_solver.helpers import (_fix_exes, _rotate_r, _valid_rotate,
+                                          rotate_r)
 
 
 def test_rotate_r():
-    assert helpers._rotate_r("1x01") == "11x0"
-    assert helpers._rotate_r("11x0") == "011x"
-    assert helpers._rotate_r("011x") == "x011"
-    assert helpers._rotate_r("x011") == "1x01"
+    assert _rotate_r(list("1x01")) == list("11x0")
+    assert _rotate_r(list("11x0")) == list("011x")
+    assert _rotate_r(list("011x")) == list("x011")
+    assert _rotate_r(list("x011")) == list("1x01")
 
-    assert helpers._valid_rotate("1x01", "11x0") is False
-    assert helpers._valid_rotate("1x01", "011x") is False
-    assert helpers._valid_rotate("1x01", "x011") is True
-    assert helpers._valid_rotate("1x01", "1x01") is True
+    assert _valid_rotate(list("1x01"), list("11x0")) is False
+    assert _valid_rotate(list("1x01"), list("011x")) is False
+    assert _valid_rotate(list("1x01"), list("x011")) is True
+    assert _valid_rotate(list("1x01"), list("1x01")) is True
 
-    assert helpers._fix_exes("1x01", "x011") == "0x11"
+    assert _fix_exes(list("1x01"), list("x011")) == list("0x11")
 
-    assert helpers.rotate_r("1x01") == "0x11"
+    assert rotate_r(list("1x01")) == list("0x11")