1+ from collections import Counter
12from collections .abc import Collection , Sequence
23from typing import Any
34
@@ -61,6 +62,32 @@ def to_136_array(tiles: Sequence[int]) -> list[int]:
6162 results .extend (base_id + i for i in range (count ))
6263 return results
6364
65+ @staticmethod
66+ def _split_string (string : str | None , offset : int , red : int | None = None ) -> list [int ]:
67+ if not string :
68+ return []
69+
70+ counts : Counter [int ] = Counter ()
71+ result : list [int ] = []
72+
73+ explicit_aka = {"r" , "0" }
74+ for ch in string :
75+ # explicit aka markers
76+ if ch in explicit_aka and red is not None :
77+ result .append (red )
78+ continue
79+
80+ tile = offset + (int (ch ) - 1 ) * 4
81+ # numeric '5' should not map to aka id when aka support is present
82+ if red is not None and tile == red :
83+ tile += 1
84+
85+ count_of_tiles = counts [tile ]
86+ result .append (tile + count_of_tiles )
87+ counts [tile ] += 1
88+
89+ return result
90+
6491 @staticmethod
6592 def string_to_136_array (
6693 sou : str | None = None ,
@@ -76,41 +103,10 @@ def string_to_136_array(
76103 has_aka_dora has to be True for this to do that.
77104 We need it to increase readability of our tests
78105 """
79-
80- def _split_string (string : str | None , offset : int , red : int | None = None ) -> list [int ]:
81- data = []
82- temp = []
83-
84- if not string :
85- return []
86-
87- for i in string :
88- if (i in {"r" , "0" }) and has_aka_dora :
89- assert red is not None
90- temp .append (red )
91- data .append (red )
92- else :
93- tile = offset + (int (i ) - 1 ) * 4
94- if tile == red and has_aka_dora :
95- # prevent non reds to become red
96- tile += 1
97- if tile in data :
98- count_of_tiles = len ([x for x in temp if x == tile ])
99- new_tile = tile + count_of_tiles
100- data .append (new_tile )
101-
102- temp .append (tile )
103- else :
104- data .append (tile )
105- temp .append (tile )
106-
107- return data
108-
109- results = _split_string (man , 0 , FIVE_RED_MAN )
110- results += _split_string (pin , 36 , FIVE_RED_PIN )
111- results += _split_string (sou , 72 , FIVE_RED_SOU )
112- results += _split_string (honors , 108 )
113-
106+ results = TilesConverter ._split_string (man , 0 , FIVE_RED_MAN if has_aka_dora else None )
107+ results += TilesConverter ._split_string (pin , 36 , FIVE_RED_PIN if has_aka_dora else None )
108+ results += TilesConverter ._split_string (sou , 72 , FIVE_RED_SOU if has_aka_dora else None )
109+ results += TilesConverter ._split_string (honors , 108 )
114110 return results
115111
116112 @staticmethod
0 commit comments