absfuyu 3.2.0__py3-none-any.whl → 3.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +3 -10
- absfuyu/__main__.py +5 -250
- absfuyu/cli/__init__.py +51 -0
- absfuyu/cli/color.py +24 -0
- absfuyu/cli/config_group.py +56 -0
- absfuyu/cli/do_group.py +98 -0
- absfuyu/cli/game_group.py +109 -0
- absfuyu/config/__init__.py +55 -94
- absfuyu/config/config.json +0 -7
- absfuyu/core.py +5 -66
- absfuyu/everything.py +7 -9
- absfuyu/extensions/beautiful.py +30 -23
- absfuyu/extensions/dev/__init__.py +11 -8
- absfuyu/extensions/dev/password_hash.py +4 -2
- absfuyu/extensions/dev/passwordlib.py +7 -5
- absfuyu/extensions/dev/project_starter.py +4 -2
- absfuyu/extensions/dev/shutdownizer.py +148 -0
- absfuyu/extensions/extra/__init__.py +1 -2
- absfuyu/extensions/extra/data_analysis.py +110 -58
- absfuyu/fun/WGS.py +50 -26
- absfuyu/fun/__init__.py +6 -7
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +75 -81
- absfuyu/game/game_stat.py +36 -0
- absfuyu/game/sudoku.py +41 -48
- absfuyu/game/tictactoe.py +303 -548
- absfuyu/game/wordle.py +56 -47
- absfuyu/general/__init__.py +17 -7
- absfuyu/general/content.py +16 -15
- absfuyu/general/data_extension.py +314 -109
- absfuyu/general/generator.py +67 -67
- absfuyu/general/human.py +148 -78
- absfuyu/logger.py +94 -68
- absfuyu/pkg_data/__init__.py +29 -25
- absfuyu/py.typed +0 -0
- absfuyu/sort.py +61 -47
- absfuyu/tools/__init__.py +0 -1
- absfuyu/tools/converter.py +80 -62
- absfuyu/tools/keygen.py +62 -67
- absfuyu/tools/obfuscator.py +57 -53
- absfuyu/tools/stats.py +24 -24
- absfuyu/tools/web.py +10 -9
- absfuyu/util/__init__.py +38 -40
- absfuyu/util/api.py +53 -43
- absfuyu/util/json_method.py +25 -27
- absfuyu/util/lunar.py +20 -24
- absfuyu/util/path.py +362 -241
- absfuyu/util/performance.py +36 -98
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +137 -148
- absfuyu-3.4.0.dist-info/METADATA +124 -0
- absfuyu-3.4.0.dist-info/RECORD +59 -0
- {absfuyu-3.2.0.dist-info → absfuyu-3.4.0.dist-info}/WHEEL +1 -2
- {absfuyu-3.2.0.dist-info → absfuyu-3.4.0.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.2.0.dist-info → absfuyu-3.4.0.dist-info/licenses}/LICENSE +1 -1
- absfuyu/extensions/dev/pkglib.py +0 -98
- absfuyu/game/tictactoe2.py +0 -318
- absfuyu-3.2.0.dist-info/METADATA +0 -216
- absfuyu-3.2.0.dist-info/RECORD +0 -55
- absfuyu-3.2.0.dist-info/top_level.txt +0 -1
absfuyu/game/sudoku.py
CHANGED
|
@@ -12,21 +12,12 @@ Credit:
|
|
|
12
12
|
- [Solve algo](https://www.techwithtim.net/tutorials/python-programming/sudoku-solver-backtracking/)
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
# Module level
|
|
17
|
-
###########################################################################
|
|
18
|
-
__all__ = [
|
|
19
|
-
"Sudoku"
|
|
20
|
-
]
|
|
15
|
+
__all__ = ["Sudoku"]
|
|
21
16
|
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
###########################################################################
|
|
25
|
-
from typing import List
|
|
18
|
+
from typing import List, Literal, Tuple
|
|
26
19
|
|
|
27
20
|
|
|
28
|
-
# Class
|
|
29
|
-
###########################################################################
|
|
30
21
|
class Sudoku:
|
|
31
22
|
def __init__(self, sudoku_data: List[List[int]]) -> None:
|
|
32
23
|
self.data = sudoku_data
|
|
@@ -34,21 +25,23 @@ class Sudoku:
|
|
|
34
25
|
self._row_len = len(self.data)
|
|
35
26
|
self._col_len = len(self.data[0])
|
|
36
27
|
# self.solved = None
|
|
28
|
+
|
|
37
29
|
def __str__(self) -> str:
|
|
38
30
|
return f"{self.__class__.__name__}({self.export_to_string()})"
|
|
31
|
+
|
|
39
32
|
def __repr__(self) -> str:
|
|
40
33
|
return self.__str__()
|
|
41
|
-
|
|
42
|
-
def export_to_string(self, *, style:
|
|
34
|
+
|
|
35
|
+
def export_to_string(self, *, style: Literal["dot", "zero"] = "dot") -> str:
|
|
43
36
|
"""
|
|
44
37
|
Export Sudoku data to string form
|
|
45
38
|
|
|
46
39
|
Parameters
|
|
47
40
|
----------
|
|
48
|
-
style :
|
|
41
|
+
style : Literal["dot", "zero"]
|
|
49
42
|
- "zero": ``0`` is ``0``
|
|
50
43
|
- "dot": ``0`` is ``.``
|
|
51
|
-
|
|
44
|
+
|
|
52
45
|
Returns
|
|
53
46
|
-------
|
|
54
47
|
str
|
|
@@ -57,16 +50,16 @@ class Sudoku:
|
|
|
57
50
|
style_option = ["zero", "dot"]
|
|
58
51
|
if style.lower() not in style_option:
|
|
59
52
|
style = "dot"
|
|
60
|
-
|
|
53
|
+
|
|
61
54
|
out = "".join(str(self.data))
|
|
62
55
|
remove = ["[", "]", " ", ","]
|
|
63
56
|
for x in remove:
|
|
64
57
|
out = out.replace(x, "")
|
|
65
|
-
|
|
58
|
+
|
|
66
59
|
if style.startswith("zero"):
|
|
67
60
|
return out
|
|
68
61
|
elif style.startswith("dot"):
|
|
69
|
-
out = out.replace("0",".")
|
|
62
|
+
out = out.replace("0", ".")
|
|
70
63
|
return out
|
|
71
64
|
else:
|
|
72
65
|
return out
|
|
@@ -80,7 +73,7 @@ class Sudoku:
|
|
|
80
73
|
----------
|
|
81
74
|
string_data : str
|
|
82
75
|
String data
|
|
83
|
-
|
|
76
|
+
|
|
84
77
|
Returns
|
|
85
78
|
-------
|
|
86
79
|
Sudoku
|
|
@@ -102,38 +95,39 @@ class Sudoku:
|
|
|
102
95
|
"""
|
|
103
96
|
if len(string_data) == 81:
|
|
104
97
|
# Convert
|
|
105
|
-
sdk = str(string_data).replace(".","0")
|
|
106
|
-
|
|
98
|
+
sdk = str(string_data).replace(".", "0")
|
|
99
|
+
|
|
107
100
|
# Divide into 9 equal parts
|
|
108
101
|
temp = []
|
|
109
102
|
while len(sdk) != 0:
|
|
110
103
|
temp.append(sdk[:9])
|
|
111
104
|
sdk = sdk[9:]
|
|
112
|
-
|
|
105
|
+
|
|
113
106
|
# Turn into list[list[int]]
|
|
114
107
|
out = []
|
|
115
108
|
for value in temp:
|
|
116
109
|
temp_list = [int(x) for x in value]
|
|
117
110
|
out.append(temp_list)
|
|
118
|
-
|
|
111
|
+
|
|
119
112
|
else:
|
|
120
113
|
# Invalid length
|
|
121
114
|
raise ValueError("Invalid length")
|
|
122
115
|
return cls(out)
|
|
123
|
-
|
|
116
|
+
|
|
124
117
|
@classmethod
|
|
125
118
|
def hardest_sudoku(cls):
|
|
126
119
|
"""
|
|
127
|
-
Create Hardest Sudoku instance
|
|
120
|
+
Create Hardest Sudoku instance
|
|
128
121
|
([Source](https://www.telegraph.co.uk/news/science/science-news/9359579/Worlds-hardest-sudoku-can-you-crack-it.html))
|
|
129
|
-
|
|
122
|
+
|
|
130
123
|
Returns
|
|
131
124
|
-------
|
|
132
125
|
Sudoku
|
|
133
126
|
``Sudoku`` instance
|
|
134
127
|
"""
|
|
135
|
-
return cls.from_string(
|
|
136
|
-
|
|
128
|
+
return cls.from_string(
|
|
129
|
+
"8..........36......7..9.2...5...7.......457.....1...3...1....68..85...1..9....4.."
|
|
130
|
+
)
|
|
137
131
|
|
|
138
132
|
def to_board_form(self) -> str:
|
|
139
133
|
"""
|
|
@@ -144,7 +138,7 @@ class Sudoku:
|
|
|
144
138
|
str
|
|
145
139
|
Sudoku Board data that ready to print
|
|
146
140
|
|
|
147
|
-
|
|
141
|
+
|
|
148
142
|
Example:
|
|
149
143
|
--------
|
|
150
144
|
>>> demo = Sudoku.hardest_sudoku()
|
|
@@ -167,22 +161,21 @@ class Sudoku:
|
|
|
167
161
|
for row in range(self._row_len):
|
|
168
162
|
if row % 3 == 0:
|
|
169
163
|
if row == 0:
|
|
170
|
-
out_string = out_string +
|
|
164
|
+
out_string = out_string + " \u250E" + "\u2500" * 29 + "\u2512\n"
|
|
171
165
|
else:
|
|
172
|
-
out_string = out_string +
|
|
166
|
+
out_string = out_string + " \u2520" + "\u2500" * 29 + "\u2528\n"
|
|
173
167
|
|
|
174
168
|
for col in range(self._col_len):
|
|
175
169
|
if col % 3 == 0:
|
|
176
|
-
out_string +=
|
|
170
|
+
out_string += " \u2503 "
|
|
177
171
|
|
|
178
172
|
if col == 8:
|
|
179
|
-
out_string = out_string + str(self.data[row][col]) +
|
|
173
|
+
out_string = out_string + str(self.data[row][col]) + " \u2503\n"
|
|
180
174
|
else:
|
|
181
175
|
out_string = out_string + str(self.data[row][col]) + " "
|
|
182
176
|
|
|
183
|
-
out_string = out_string +
|
|
177
|
+
out_string = out_string + " \u2516" + "\u2500" * 29 + "\u251A"
|
|
184
178
|
return out_string
|
|
185
|
-
|
|
186
179
|
|
|
187
180
|
# Solve
|
|
188
181
|
def _find_empty(self):
|
|
@@ -200,15 +193,15 @@ class Sudoku:
|
|
|
200
193
|
return (row, col)
|
|
201
194
|
# Return None when there is no empty cell
|
|
202
195
|
return None
|
|
203
|
-
|
|
204
|
-
def _is_valid(self, number: int, position:
|
|
196
|
+
|
|
197
|
+
def _is_valid(self, number: int, position: Tuple[int, int]) -> bool:
|
|
205
198
|
"""
|
|
206
199
|
Check valid number value in row, column, box
|
|
207
200
|
"""
|
|
208
|
-
row, col = position
|
|
201
|
+
row, col = position # unpack tuple
|
|
209
202
|
|
|
210
203
|
# Check row
|
|
211
|
-
for i in range(self._col_len):
|
|
204
|
+
for i in range(self._col_len): # each item in row i; row i has `col_len` items
|
|
212
205
|
if self.data[row][i] == number and col != i:
|
|
213
206
|
return False
|
|
214
207
|
|
|
@@ -236,12 +229,12 @@ class Sudoku:
|
|
|
236
229
|
# Find empty cell
|
|
237
230
|
empty_pos = self._find_empty()
|
|
238
231
|
if empty_pos is None:
|
|
239
|
-
return True
|
|
232
|
+
return True # solve_state (True: every cell filled)
|
|
240
233
|
else:
|
|
241
234
|
# unpack position when exist empty cell
|
|
242
235
|
row, col = empty_pos
|
|
243
236
|
|
|
244
|
-
for num in range(1,10):
|
|
237
|
+
for num in range(1, 10): # sudoku value (1-9)
|
|
245
238
|
if self._is_valid(num, empty_pos):
|
|
246
239
|
self.data[row][col] = num
|
|
247
240
|
|
|
@@ -253,17 +246,17 @@ class Sudoku:
|
|
|
253
246
|
|
|
254
247
|
# End recursive
|
|
255
248
|
return False
|
|
256
|
-
|
|
249
|
+
|
|
257
250
|
def solve(self):
|
|
258
251
|
"""
|
|
259
252
|
Solve the Sudoku
|
|
260
|
-
|
|
253
|
+
|
|
261
254
|
Returns
|
|
262
255
|
-------
|
|
263
256
|
Sudoku
|
|
264
257
|
``Sudoku`` instance
|
|
265
|
-
|
|
266
|
-
|
|
258
|
+
|
|
259
|
+
|
|
267
260
|
Example:
|
|
268
261
|
--------
|
|
269
262
|
>>> test = Sudoku.hardest_sudoku()
|
|
@@ -286,11 +279,11 @@ class Sudoku:
|
|
|
286
279
|
self._solve()
|
|
287
280
|
# self.solved = self.data
|
|
288
281
|
# self.data = self._original
|
|
289
|
-
return __class__(self.data)
|
|
290
|
-
|
|
282
|
+
return self.__class__(self.data)
|
|
283
|
+
|
|
291
284
|
|
|
292
285
|
# Run
|
|
293
286
|
###########################################################################
|
|
294
287
|
if __name__ == "__main__":
|
|
295
288
|
test = Sudoku.hardest_sudoku()
|
|
296
|
-
print(test.solve().to_board_form())
|
|
289
|
+
print(test.solve().to_board_form())
|