absfuyu 3.0.0__py3-none-any.whl → 3.1.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/config/config.json +1 -1
- absfuyu/extensions/dev/__init__.py +142 -2
- absfuyu/extensions/extra/data_analysis.py +687 -119
- absfuyu/fun/tarot.py +9 -7
- absfuyu/game/tictactoe2.py +90 -78
- absfuyu/general/data_extension.py +147 -11
- absfuyu/general/generator.py +65 -4
- absfuyu/general/human.py +27 -2
- absfuyu/util/performance.py +101 -14
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/METADATA +23 -23
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/RECORD +15 -15
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/LICENSE +0 -0
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/WHEEL +0 -0
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-3.0.0.dist-info → absfuyu-3.1.0.dist-info}/top_level.txt +0 -0
absfuyu/fun/tarot.py
CHANGED
|
@@ -4,8 +4,8 @@ Absfuyu: Tarot
|
|
|
4
4
|
Tarot stuff
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
Version: 1.0.
|
|
8
|
-
Date updated:
|
|
7
|
+
Version: 1.0.3
|
|
8
|
+
Date updated: 01/01/2024 (dd/mm/yyyy)
|
|
9
9
|
|
|
10
10
|
Usage:
|
|
11
11
|
------
|
|
@@ -23,8 +23,8 @@ __all__ = ["Tarot", "TarotCard"]
|
|
|
23
23
|
import random
|
|
24
24
|
from typing import Dict, List
|
|
25
25
|
|
|
26
|
-
from absfuyu.core import DATA_PATH
|
|
27
26
|
from absfuyu.logger import logger
|
|
27
|
+
from absfuyu.pkg_data import DataList
|
|
28
28
|
from absfuyu.util.pkl import Pickler
|
|
29
29
|
|
|
30
30
|
|
|
@@ -60,7 +60,7 @@ class Tarot:
|
|
|
60
60
|
"""Tarot data"""
|
|
61
61
|
|
|
62
62
|
def __init__(self) -> None:
|
|
63
|
-
self.data_location =
|
|
63
|
+
self.data_location = DataList.TAROT
|
|
64
64
|
|
|
65
65
|
def __str__(self) -> str:
|
|
66
66
|
return f"{self.__class__.__name__}()"
|
|
@@ -68,9 +68,10 @@ class Tarot:
|
|
|
68
68
|
def __repr__(self) -> str:
|
|
69
69
|
return self.__str__()
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
@property
|
|
72
|
+
def tarot_deck(self) -> List[TarotCard]:
|
|
72
73
|
"""
|
|
73
|
-
Load tarot
|
|
74
|
+
Load pickled tarot data
|
|
74
75
|
|
|
75
76
|
:rtype: list[TarotCard]
|
|
76
77
|
"""
|
|
@@ -97,10 +98,11 @@ class Tarot:
|
|
|
97
98
|
TarotCard
|
|
98
99
|
Random Tarot card
|
|
99
100
|
"""
|
|
100
|
-
return random.choice(self.
|
|
101
|
+
return random.choice(self.tarot_deck)
|
|
101
102
|
|
|
102
103
|
|
|
103
104
|
# Run
|
|
104
105
|
###########################################################################
|
|
105
106
|
if __name__ == "__main__":
|
|
107
|
+
logger.setLevel(10)
|
|
106
108
|
pass
|
absfuyu/game/tictactoe2.py
CHANGED
|
@@ -2,24 +2,22 @@
|
|
|
2
2
|
Game: Tic Tac Toe
|
|
3
3
|
-----------------
|
|
4
4
|
|
|
5
|
-
Version: 2.0.
|
|
6
|
-
Date updated:
|
|
5
|
+
Version: 2.0.2
|
|
6
|
+
Date updated: 04/12/2023 (mm/dd/yyyy)
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
11
11
|
###########################################################################
|
|
12
|
-
__all__ = [
|
|
13
|
-
"TicTacToe", "GameMode"
|
|
14
|
-
]
|
|
12
|
+
__all__ = ["TicTacToe", "GameMode"]
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
# Library
|
|
18
16
|
###########################################################################
|
|
19
|
-
from collections import namedtuple
|
|
17
|
+
# from collections import namedtuple
|
|
20
18
|
import random
|
|
21
19
|
import time
|
|
22
|
-
from typing import Dict, List, Union
|
|
20
|
+
from typing import Dict, List, NamedTuple, Union
|
|
23
21
|
|
|
24
22
|
from absfuyu.core import CLITextColor
|
|
25
23
|
|
|
@@ -27,7 +25,12 @@ from absfuyu.core import CLITextColor
|
|
|
27
25
|
# Class
|
|
28
26
|
###########################################################################
|
|
29
27
|
BoardGame = List[List[str]]
|
|
30
|
-
Pos = namedtuple("Pos", ["row", "col"])
|
|
28
|
+
# Pos = namedtuple("Pos", ["row", "col"]) # Position
|
|
29
|
+
class Pos(NamedTuple):
|
|
30
|
+
"""Position"""
|
|
31
|
+
row: int
|
|
32
|
+
col: int
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
class GameMode:
|
|
33
36
|
ONE_V_ONE = "1v1"
|
|
@@ -37,18 +40,18 @@ class GameMode:
|
|
|
37
40
|
|
|
38
41
|
class TicTacToe:
|
|
39
42
|
"""Tic Tac Toe game"""
|
|
43
|
+
|
|
40
44
|
def __init__(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
) -> None:
|
|
45
|
+
self,
|
|
46
|
+
game_size: int = 3,
|
|
47
|
+
*,
|
|
48
|
+
x: str = "X",
|
|
49
|
+
o: str = "O",
|
|
50
|
+
blank: str = " ",
|
|
51
|
+
position_split_symbol: str = ",",
|
|
52
|
+
end_break_word: str = "END",
|
|
53
|
+
welcome_message: bool = True,
|
|
54
|
+
) -> None:
|
|
52
55
|
"""
|
|
53
56
|
:param game_size: Board size (Default: 3x3)
|
|
54
57
|
:param x: X symbol
|
|
@@ -76,56 +79,57 @@ class TicTacToe:
|
|
|
76
79
|
|
|
77
80
|
def __str__(self) -> str:
|
|
78
81
|
return f"{self.__class__.__name__}(game_size={self.row_size})"
|
|
82
|
+
|
|
79
83
|
def __repr__(self) -> str:
|
|
80
84
|
return self.__str__()
|
|
81
|
-
|
|
85
|
+
|
|
82
86
|
# Game
|
|
83
87
|
def _gen_board(self) -> BoardGame:
|
|
84
88
|
"""
|
|
85
89
|
Generate board game
|
|
86
90
|
"""
|
|
87
91
|
board = [
|
|
88
|
-
[self.BLANK for _ in range(self.row_size)]
|
|
89
|
-
for _ in range(self.col_size)
|
|
92
|
+
[self.BLANK for _ in range(self.row_size)] for _ in range(self.col_size)
|
|
90
93
|
]
|
|
91
94
|
return board
|
|
92
|
-
|
|
95
|
+
|
|
93
96
|
def _check_state(self) -> Dict[str, Union[str, int]]:
|
|
94
97
|
"""
|
|
95
98
|
Check game winning state
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
dict[str, str | int]
|
|
103
|
+
``X`` | ``O`` | ``BLANK``
|
|
100
104
|
"""
|
|
101
105
|
|
|
102
106
|
# Check rows
|
|
103
107
|
for row in range(self.row_size):
|
|
104
108
|
if len(set(self.board[row])) == 1:
|
|
105
109
|
key = list(set(self.board[row]))[0]
|
|
106
|
-
return {"key": key, "location": "row", "pos": row}
|
|
110
|
+
return {"key": key, "location": "row", "pos": row} # modified
|
|
107
111
|
|
|
108
112
|
# Check cols
|
|
109
113
|
for col in range(self.col_size):
|
|
110
114
|
temp = [self.board[row][col] for row in range(self.row_size)]
|
|
111
115
|
if len(set(temp)) == 1:
|
|
112
116
|
key = list(set(temp))[0]
|
|
113
|
-
return {"key": key, "location": "col", "pos": col}
|
|
114
|
-
|
|
117
|
+
return {"key": key, "location": "col", "pos": col} # modified
|
|
118
|
+
|
|
115
119
|
# Check diagonal
|
|
116
120
|
diag1 = [self.board[i][i] for i in range(len(self.board))]
|
|
117
121
|
if len(set(diag1)) == 1:
|
|
118
122
|
key = list(set(diag1))[0]
|
|
119
|
-
return {"key": key, "location": "diag", "pos": 1}
|
|
120
|
-
|
|
121
|
-
diag2 = [self.board[i][len(self.board)-i-1] for i in range(len(self.board))]
|
|
123
|
+
return {"key": key, "location": "diag", "pos": 1} # modified
|
|
124
|
+
|
|
125
|
+
diag2 = [self.board[i][len(self.board) - i - 1] for i in range(len(self.board))]
|
|
122
126
|
if len(set(diag2)) == 1:
|
|
123
127
|
key = list(set(diag2))[0]
|
|
124
|
-
return {"key": key, "location": "diag", "pos": 2}
|
|
125
|
-
|
|
128
|
+
return {"key": key, "location": "diag", "pos": 2} # modified
|
|
129
|
+
|
|
126
130
|
# Else
|
|
127
131
|
return {"key": self.BLANK}
|
|
128
|
-
|
|
132
|
+
|
|
129
133
|
@staticmethod
|
|
130
134
|
def _print_board(board: BoardGame) -> None:
|
|
131
135
|
"""
|
|
@@ -138,7 +142,7 @@ class TicTacToe:
|
|
|
138
142
|
for col in range(ncol):
|
|
139
143
|
print(f"| {board[row][col]} ", end="")
|
|
140
144
|
print(f"|\n{'+---'*length}+")
|
|
141
|
-
|
|
145
|
+
|
|
142
146
|
def _win_hightlight(self) -> BoardGame:
|
|
143
147
|
"""
|
|
144
148
|
Hight light the win by removing other placed key
|
|
@@ -165,44 +169,44 @@ class TicTacToe:
|
|
|
165
169
|
board[i][i] = detail["key"]
|
|
166
170
|
else:
|
|
167
171
|
for i in range(len(board)):
|
|
168
|
-
board[i][len(board)-i-1] = detail["key"]
|
|
169
|
-
|
|
172
|
+
board[i][len(board) - i - 1] = detail["key"]
|
|
173
|
+
|
|
170
174
|
# Output
|
|
171
175
|
return board
|
|
172
|
-
|
|
176
|
+
|
|
173
177
|
def _is_blank(self, pos: Pos) -> bool:
|
|
174
178
|
"""Check if current pos is filled"""
|
|
175
179
|
return self.board[pos.row][pos.col] == self.BLANK
|
|
176
180
|
|
|
177
181
|
@staticmethod
|
|
178
|
-
def _convert_bot_output(pos: Pos):
|
|
182
|
+
def _convert_bot_output(pos: Pos) -> Pos:
|
|
179
183
|
"""
|
|
180
184
|
Turn to real pos by:
|
|
181
|
-
|
|
182
|
-
-
|
|
185
|
+
|
|
186
|
+
- +1 to ``row`` and ``col``
|
|
187
|
+
- convert into ``str``
|
|
183
188
|
"""
|
|
184
189
|
return Pos(pos.row + 1, pos.col + 1)
|
|
185
|
-
|
|
186
|
-
def _generate_random_move(self):
|
|
190
|
+
|
|
191
|
+
def _generate_random_move(self) -> Pos:
|
|
187
192
|
"""
|
|
188
193
|
Generate a random move from board game
|
|
189
194
|
"""
|
|
190
195
|
while True:
|
|
191
196
|
output = Pos(
|
|
192
|
-
random.randint(0, len(self.board)-1),
|
|
193
|
-
random.randint(0, len(self.board)-1)
|
|
197
|
+
random.randint(0, len(self.board) - 1),
|
|
198
|
+
random.randint(0, len(self.board) - 1),
|
|
194
199
|
)
|
|
195
200
|
if self._is_blank(output):
|
|
196
201
|
break
|
|
197
202
|
return self._convert_bot_output(output)
|
|
198
203
|
|
|
199
|
-
|
|
200
204
|
def play(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
self,
|
|
206
|
+
game_mode: str = GameMode.ONE_V_BOT,
|
|
207
|
+
*,
|
|
208
|
+
bot_time: float = 0,
|
|
209
|
+
) -> None:
|
|
206
210
|
"""
|
|
207
211
|
Play a game of Tic Tac Toe
|
|
208
212
|
|
|
@@ -210,7 +214,7 @@ class TicTacToe:
|
|
|
210
214
|
----------
|
|
211
215
|
game_mode : str
|
|
212
216
|
Game mode
|
|
213
|
-
|
|
217
|
+
|
|
214
218
|
bot_time : float
|
|
215
219
|
Time sleep between each bot move (Default: ``0``)
|
|
216
220
|
"""
|
|
@@ -223,63 +227,71 @@ class TicTacToe:
|
|
|
223
227
|
|
|
224
228
|
# Welcome message
|
|
225
229
|
if self.welcome_message:
|
|
226
|
-
print(
|
|
230
|
+
print(
|
|
231
|
+
f"""\
|
|
227
232
|
{CLITextColor.GREEN}Welcome to Tic Tac Toe!
|
|
228
233
|
|
|
229
234
|
{CLITextColor.YELLOW}Rules: Match lines vertically, horizontally or diagonally
|
|
230
235
|
{CLITextColor.YELLOW}{self.X} goes first, then {self.O}
|
|
231
|
-
{CLITextColor.RED}Type '{self.END_BREAK}' to end the game{CLITextColor.RESET}"""
|
|
232
|
-
|
|
236
|
+
{CLITextColor.RED}Type '{self.END_BREAK}' to end the game{CLITextColor.RESET}"""
|
|
237
|
+
)
|
|
238
|
+
|
|
233
239
|
# Check gamemode
|
|
234
240
|
_game_mode = [
|
|
235
|
-
"1v1",
|
|
236
|
-
"1v0",
|
|
237
|
-
"0v0"
|
|
241
|
+
"1v1", # Player vs player
|
|
242
|
+
"1v0", # Player vs BOT
|
|
243
|
+
"0v0", # BOT vs BOT
|
|
238
244
|
]
|
|
239
245
|
if game_mode not in _game_mode:
|
|
240
|
-
game_mode = _game_mode[1]
|
|
246
|
+
game_mode = _game_mode[1] # Force vs BOT
|
|
241
247
|
if game_mode.startswith(GameMode.ONE_V_BOT):
|
|
242
248
|
BOT = True
|
|
243
249
|
if game_mode.startswith(GameMode.BOT_V_BOT):
|
|
244
250
|
BOT = True
|
|
245
251
|
BOT2 = True
|
|
246
|
-
|
|
252
|
+
|
|
247
253
|
# Game
|
|
248
254
|
self._print_board(self.board)
|
|
249
255
|
|
|
250
256
|
place_pos = None
|
|
251
257
|
while state == self.BLANK and filled < self.row_size**2:
|
|
252
258
|
print(f"{CLITextColor.BLUE}{current_player}'s turn:{CLITextColor.RESET}")
|
|
253
|
-
|
|
254
|
-
try:
|
|
259
|
+
|
|
260
|
+
try: # Error handling
|
|
255
261
|
if (BOT and current_player == self.O) or BOT2:
|
|
256
262
|
move = self._generate_random_move()
|
|
257
263
|
str_move = f"{move.row}{self.POS_SPLIT}{move.col}"
|
|
258
264
|
move = str_move
|
|
259
265
|
else:
|
|
260
|
-
move = input(
|
|
266
|
+
move = input(
|
|
267
|
+
f"Place {CLITextColor.BLUE}{current_player}{CLITextColor.RESET} at {CLITextColor.BLUE}<row{self.POS_SPLIT}col>:{CLITextColor.RESET} "
|
|
268
|
+
)
|
|
261
269
|
|
|
262
|
-
if move.upper() == self.END_BREAK:
|
|
270
|
+
if move.upper() == self.END_BREAK: # Failsafe
|
|
263
271
|
print(f"{CLITextColor.RED}Game ended{CLITextColor.RESET}")
|
|
264
272
|
break
|
|
265
|
-
|
|
273
|
+
|
|
266
274
|
move = move.split(self.POS_SPLIT)
|
|
267
275
|
row = int(move[0])
|
|
268
276
|
col = int(move[1])
|
|
269
|
-
place_pos = Pos(row-1, col-1)
|
|
277
|
+
place_pos = Pos(row - 1, col - 1)
|
|
270
278
|
|
|
271
279
|
if self._is_blank(place_pos):
|
|
272
280
|
self.board[place_pos.row][place_pos.col] = current_player
|
|
273
281
|
filled += 1
|
|
274
|
-
|
|
275
|
-
else:
|
|
276
|
-
print(
|
|
282
|
+
|
|
283
|
+
else: # User and BOT error
|
|
284
|
+
print(
|
|
285
|
+
f"{CLITextColor.RED}Invalid move, please try again{CLITextColor.RESET}"
|
|
286
|
+
)
|
|
277
287
|
continue
|
|
278
|
-
|
|
279
|
-
except:
|
|
280
|
-
print(
|
|
288
|
+
|
|
289
|
+
except: # User error
|
|
290
|
+
print(
|
|
291
|
+
f"{CLITextColor.RED}Invalid move, please try again{CLITextColor.RESET}"
|
|
292
|
+
)
|
|
281
293
|
continue
|
|
282
|
-
|
|
294
|
+
|
|
283
295
|
state = self._check_state()["key"]
|
|
284
296
|
self._print_board(self.board)
|
|
285
297
|
|
|
@@ -288,9 +300,9 @@ class TicTacToe:
|
|
|
288
300
|
self._print_board(self._win_hightlight())
|
|
289
301
|
|
|
290
302
|
# Change turn
|
|
291
|
-
if BOT2:
|
|
303
|
+
if BOT2: # BOT delay
|
|
292
304
|
time.sleep(bot_time)
|
|
293
|
-
|
|
305
|
+
|
|
294
306
|
if current_player == self.X:
|
|
295
307
|
current_player = self.O
|
|
296
308
|
else:
|
|
@@ -303,4 +315,4 @@ class TicTacToe:
|
|
|
303
315
|
# Run
|
|
304
316
|
###########################################################################
|
|
305
317
|
if __name__ == "__main__":
|
|
306
|
-
pass
|
|
318
|
+
pass
|
|
@@ -3,8 +3,8 @@ Absfuyu: Data extension
|
|
|
3
3
|
-----------------------
|
|
4
4
|
Extension for data type such as ``list``, ``str``, ``dict``, ...
|
|
5
5
|
|
|
6
|
-
Version: 1.
|
|
7
|
-
Date updated: 01/
|
|
6
|
+
Version: 1.12.3
|
|
7
|
+
Date updated: 23/01/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Features:
|
|
10
10
|
---------
|
|
@@ -30,8 +30,10 @@ __all__ = [
|
|
|
30
30
|
# Sub
|
|
31
31
|
"Pow",
|
|
32
32
|
"ListREPR",
|
|
33
|
+
"ListNoDunder",
|
|
33
34
|
"DictBoolTrue",
|
|
34
35
|
"DictBoolFalse",
|
|
36
|
+
# "DictNoDunder",
|
|
35
37
|
]
|
|
36
38
|
|
|
37
39
|
|
|
@@ -42,7 +44,8 @@ from itertools import accumulate, chain, groupby
|
|
|
42
44
|
import math
|
|
43
45
|
import operator
|
|
44
46
|
import random
|
|
45
|
-
from typing import Any, Dict, List, Optional, Union
|
|
47
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
48
|
+
from sys import version_info as python_version
|
|
46
49
|
|
|
47
50
|
from absfuyu.general.generator import Generator, Charset
|
|
48
51
|
from absfuyu.logger import logger, _compress_list_for_print
|
|
@@ -109,6 +112,14 @@ class ListREPR(list):
|
|
|
109
112
|
return _compress_list_for_print(self, 9)
|
|
110
113
|
|
|
111
114
|
|
|
115
|
+
class ListNoDunder(List[str]):
|
|
116
|
+
"""Use with ``object.__dir__()``"""
|
|
117
|
+
|
|
118
|
+
def __repr__(self) -> str:
|
|
119
|
+
out = [x for x in self if not x.startswith("__")]
|
|
120
|
+
return out.__repr__()
|
|
121
|
+
|
|
122
|
+
|
|
112
123
|
class DictBoolTrue(Dict[Any, bool]):
|
|
113
124
|
"""Only show items when ``values == True`` in ``__repr__()``"""
|
|
114
125
|
|
|
@@ -125,6 +136,18 @@ class DictBoolFalse(Dict[Any, bool]):
|
|
|
125
136
|
return _dict_bool(temp, False).__repr__()
|
|
126
137
|
|
|
127
138
|
|
|
139
|
+
# class DictNoDunder(dict): # W.I.P
|
|
140
|
+
# """Remove dunder methods in ``__repr__()`` of dict"""
|
|
141
|
+
|
|
142
|
+
# def __repr__(self) -> str:
|
|
143
|
+
# temp = self.copy()
|
|
144
|
+
# out = dict()
|
|
145
|
+
# for k, v in temp.items():
|
|
146
|
+
# if not str(k).startswith("__"):
|
|
147
|
+
# out.__setattr__(k, v)
|
|
148
|
+
# return out.__repr__()
|
|
149
|
+
|
|
150
|
+
|
|
128
151
|
# Class
|
|
129
152
|
###########################################################################
|
|
130
153
|
class Text(str):
|
|
@@ -419,6 +442,48 @@ class Text(str):
|
|
|
419
442
|
logger.debug(temp)
|
|
420
443
|
return __class__("".join(temp))
|
|
421
444
|
|
|
445
|
+
def reverse_capslock(self) -> "Text":
|
|
446
|
+
"""
|
|
447
|
+
Reverse capslock in string
|
|
448
|
+
|
|
449
|
+
Returns
|
|
450
|
+
-------
|
|
451
|
+
Text
|
|
452
|
+
Reversed capslock ``Text``
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
Example:
|
|
456
|
+
--------
|
|
457
|
+
>>> test = Text("Foo")
|
|
458
|
+
>>> test.reverse_capslock()
|
|
459
|
+
'fOO'
|
|
460
|
+
"""
|
|
461
|
+
temp = list(self)
|
|
462
|
+
for i, x in enumerate(temp):
|
|
463
|
+
if x.isupper():
|
|
464
|
+
temp[i] = x.lower()
|
|
465
|
+
else:
|
|
466
|
+
temp[i] = x.upper()
|
|
467
|
+
return __class__("".join(temp))
|
|
468
|
+
|
|
469
|
+
def to_list(self) -> List[str]:
|
|
470
|
+
"""
|
|
471
|
+
Convert into list
|
|
472
|
+
|
|
473
|
+
Returns
|
|
474
|
+
-------
|
|
475
|
+
list[str]
|
|
476
|
+
List of string
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
Example:
|
|
480
|
+
--------
|
|
481
|
+
>>> test = Text("test")
|
|
482
|
+
>>> test.to_list()
|
|
483
|
+
['t', 'e', 's', 't']
|
|
484
|
+
"""
|
|
485
|
+
return list(self)
|
|
486
|
+
|
|
422
487
|
|
|
423
488
|
class IntNumber(int):
|
|
424
489
|
"""
|
|
@@ -776,7 +841,10 @@ class IntNumber(int):
|
|
|
776
841
|
>>> test.gcd(8)
|
|
777
842
|
8
|
|
778
843
|
"""
|
|
779
|
-
|
|
844
|
+
if python_version.micro < 9:
|
|
845
|
+
return __class__(math.gcd(self, with_number))
|
|
846
|
+
else:
|
|
847
|
+
return __class__(math.lcm(self, with_number))
|
|
780
848
|
|
|
781
849
|
def add_to_one_digit(self, master_number: bool = False) -> "IntNumber":
|
|
782
850
|
"""
|
|
@@ -806,7 +874,7 @@ class IntNumber(int):
|
|
|
806
874
|
11
|
|
807
875
|
"""
|
|
808
876
|
number = self
|
|
809
|
-
if number
|
|
877
|
+
if number < 0:
|
|
810
878
|
number *= -1
|
|
811
879
|
logger.debug(f"Current number: {number}")
|
|
812
880
|
while len(str(number)) != 1:
|
|
@@ -847,7 +915,8 @@ class IntNumber(int):
|
|
|
847
915
|
divi_list = [x for x in range(1, int(self / 2) + 1) if self % x == 0] + [self]
|
|
848
916
|
|
|
849
917
|
if short_form:
|
|
850
|
-
return
|
|
918
|
+
return divi_list
|
|
919
|
+
# return ListREPR(divi_list) ## FIX LATER
|
|
851
920
|
return divi_list
|
|
852
921
|
|
|
853
922
|
def prime_factor(self, short_form: bool = True) -> Union[List[int], List[Pow]]:
|
|
@@ -921,8 +990,8 @@ class IntNumber(int):
|
|
|
921
990
|
>>> test = IntNumber(1024)
|
|
922
991
|
>>> test.analyze()
|
|
923
992
|
{
|
|
924
|
-
'summary': {'number': 1024, 'length': 4, 'even': True, 'prime factor': [2^10], 'divisible': [1, 2, 4, 8,
|
|
925
|
-
'convert': {'binary': '10000000000', 'reverse': 4201, 'add to one': 7},
|
|
993
|
+
'summary': {'number': 1024, 'length': 4, 'even': True, 'prime factor': [2^10], 'divisible': [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]},
|
|
994
|
+
'convert': {'binary': '10000000000', 'octa': '2000', 'hex': '400', 'reverse': 4201, 'add to one': 7},
|
|
926
995
|
'characteristic': {'prime': False, 'twisted prime': False, 'perfect': False, 'narcissistic': False, 'palindromic': False, 'palindromic prime': False}
|
|
927
996
|
}
|
|
928
997
|
"""
|
|
@@ -935,7 +1004,10 @@ class IntNumber(int):
|
|
|
935
1004
|
"divisible": self.divisible_list(short_form=short_form),
|
|
936
1005
|
},
|
|
937
1006
|
"convert": {
|
|
938
|
-
"binary": self
|
|
1007
|
+
"binary": bin(self)[2:],
|
|
1008
|
+
"octa": oct(self)[2:],
|
|
1009
|
+
"hex": hex(self)[2:],
|
|
1010
|
+
# "hash": hash(self),
|
|
939
1011
|
"reverse": self.reverse(),
|
|
940
1012
|
"add to one": self.add_to_one_digit(),
|
|
941
1013
|
},
|
|
@@ -1235,7 +1307,7 @@ class ListExt(list):
|
|
|
1235
1307
|
logger.debug(out)
|
|
1236
1308
|
return out
|
|
1237
1309
|
|
|
1238
|
-
def apply(self, func) -> "ListExt":
|
|
1310
|
+
def apply(self, func: Callable) -> "ListExt":
|
|
1239
1311
|
"""
|
|
1240
1312
|
Apply function to each entry
|
|
1241
1313
|
|
|
@@ -1301,6 +1373,13 @@ class ListExt(list):
|
|
|
1301
1373
|
temp = groupby(self.sorts())
|
|
1302
1374
|
return __class__([list(g) for _, g in temp])
|
|
1303
1375
|
|
|
1376
|
+
@staticmethod
|
|
1377
|
+
def _group_by_unique(iterable: list) -> List[list]:
|
|
1378
|
+
"""
|
|
1379
|
+
Static method for ``group_by_unique``
|
|
1380
|
+
"""
|
|
1381
|
+
return list([list(g) for _, g in groupby(iterable)])
|
|
1382
|
+
|
|
1304
1383
|
def group_by_pair_value(self, max_loop: int = 3) -> List[list]:
|
|
1305
1384
|
"""
|
|
1306
1385
|
Assume each ``list`` in ``list`` is a pair value,
|
|
@@ -1353,6 +1432,62 @@ class ListExt(list):
|
|
|
1353
1432
|
|
|
1354
1433
|
return list(x for x, _ in groupby(iter))
|
|
1355
1434
|
|
|
1435
|
+
def flatten(self) -> "ListExt":
|
|
1436
|
+
"""
|
|
1437
|
+
Flatten the list
|
|
1438
|
+
|
|
1439
|
+
Returns
|
|
1440
|
+
-------
|
|
1441
|
+
ListExt
|
|
1442
|
+
Flattened list
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
Example:
|
|
1446
|
+
--------
|
|
1447
|
+
>>> test = ListExt([["test"], ["test", "test"], ["test"]])
|
|
1448
|
+
>>> test.flatten()
|
|
1449
|
+
['test', 'test', 'test', 'test']
|
|
1450
|
+
"""
|
|
1451
|
+
try:
|
|
1452
|
+
return ListExt(chain(*self))
|
|
1453
|
+
except:
|
|
1454
|
+
temp = list(map(lambda x: x if isinstance(x, list) else [x], self))
|
|
1455
|
+
return ListExt(chain(*temp))
|
|
1456
|
+
|
|
1457
|
+
def numbering(self, start: int = 0) -> "ListExt":
|
|
1458
|
+
"""
|
|
1459
|
+
Number the item in list
|
|
1460
|
+
(``enumerate`` wrapper)
|
|
1461
|
+
|
|
1462
|
+
Parameters
|
|
1463
|
+
----------
|
|
1464
|
+
start : int
|
|
1465
|
+
Start from which number
|
|
1466
|
+
(Default: ``0``)
|
|
1467
|
+
|
|
1468
|
+
Returns
|
|
1469
|
+
-------
|
|
1470
|
+
ListExt
|
|
1471
|
+
Counted list
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
Example:
|
|
1475
|
+
--------
|
|
1476
|
+
>>> test = ListExt([9, 9, 9])
|
|
1477
|
+
>>> test.numbering()
|
|
1478
|
+
[(0, 9), (1, 9), (2, 9)]
|
|
1479
|
+
"""
|
|
1480
|
+
start = set_min(start, min_value=0)
|
|
1481
|
+
return ListExt(enumerate(self, start=start))
|
|
1482
|
+
|
|
1483
|
+
@staticmethod
|
|
1484
|
+
def _numbering(iterable: list, start: int = 0) -> List[Tuple[int, Any]]:
|
|
1485
|
+
"""
|
|
1486
|
+
Static method for ``numbering``
|
|
1487
|
+
"""
|
|
1488
|
+
start = set_min(start, min_value=0)
|
|
1489
|
+
return list(enumerate(iterable, start=start))
|
|
1490
|
+
|
|
1356
1491
|
|
|
1357
1492
|
class DictExt(dict):
|
|
1358
1493
|
"""
|
|
@@ -1434,7 +1569,7 @@ class DictExt(dict):
|
|
|
1434
1569
|
"""
|
|
1435
1570
|
return __class__(zip(self.values(), self.keys()))
|
|
1436
1571
|
|
|
1437
|
-
def apply(self, func, apply_to_value: bool = True) -> "DictExt":
|
|
1572
|
+
def apply(self, func: Callable, apply_to_value: bool = True) -> "DictExt":
|
|
1438
1573
|
"""
|
|
1439
1574
|
Apply function to ``DictExt.keys()`` or ``DictExt.values()``
|
|
1440
1575
|
|
|
@@ -1472,3 +1607,4 @@ class DictExt(dict):
|
|
|
1472
1607
|
###########################################################################
|
|
1473
1608
|
if __name__ == "__main__":
|
|
1474
1609
|
logger.setLevel(10)
|
|
1610
|
+
# from rich import print
|