absfuyu 5.1.0__py3-none-any.whl → 5.3.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 +1 -1
- absfuyu/__main__.py +3 -3
- absfuyu/cli/__init__.py +1 -1
- absfuyu/cli/color.py +3 -3
- absfuyu/cli/config_group.py +2 -2
- absfuyu/cli/do_group.py +12 -2
- absfuyu/cli/game_group.py +2 -2
- absfuyu/cli/tool_group.py +2 -3
- absfuyu/config/__init__.py +1 -1
- absfuyu/core/__init__.py +1 -1
- absfuyu/core/baseclass.py +32 -2
- absfuyu/core/baseclass2.py +1 -1
- absfuyu/core/decorator.py +4 -4
- absfuyu/core/docstring.py +43 -25
- absfuyu/core/dummy_cli.py +1 -1
- absfuyu/core/dummy_func.py +4 -4
- absfuyu/dxt/__init__.py +1 -1
- absfuyu/dxt/dictext.py +5 -2
- absfuyu/dxt/dxt_support.py +1 -1
- absfuyu/dxt/intext.py +5 -2
- absfuyu/dxt/listext.py +405 -127
- absfuyu/dxt/strext.py +75 -15
- absfuyu/extra/__init__.py +1 -1
- absfuyu/extra/beautiful.py +1 -1
- absfuyu/extra/da/__init__.py +1 -1
- absfuyu/extra/da/dadf.py +56 -4
- absfuyu/extra/da/dadf_base.py +1 -1
- absfuyu/extra/da/df_func.py +1 -1
- absfuyu/extra/da/mplt.py +1 -1
- absfuyu/extra/data_analysis.py +3 -3
- absfuyu/fun/__init__.py +1 -1
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +1 -1
- absfuyu/game/game_stat.py +1 -1
- absfuyu/game/sudoku.py +1 -1
- absfuyu/game/tictactoe.py +2 -3
- absfuyu/game/wordle.py +1 -1
- absfuyu/general/__init__.py +1 -1
- absfuyu/general/content.py +2 -2
- absfuyu/general/human.py +1 -1
- absfuyu/general/shape.py +1 -1
- absfuyu/logger.py +1 -1
- absfuyu/pkg_data/__init__.py +1 -1
- absfuyu/pkg_data/deprecated.py +1 -1
- absfuyu/sort.py +1 -1
- absfuyu/tools/__init__.py +16 -13
- absfuyu/tools/checksum.py +2 -2
- absfuyu/tools/converter.py +29 -8
- absfuyu/tools/generator.py +251 -110
- absfuyu/tools/inspector.py +84 -40
- absfuyu/tools/keygen.py +1 -1
- absfuyu/tools/obfuscator.py +2 -2
- absfuyu/tools/passwordlib.py +3 -4
- absfuyu/tools/shutdownizer.py +1 -1
- absfuyu/tools/web.py +1 -1
- absfuyu/typings.py +136 -0
- absfuyu/util/__init__.py +18 -4
- absfuyu/util/api.py +36 -16
- absfuyu/util/json_method.py +43 -14
- absfuyu/util/lunar.py +1 -1
- absfuyu/util/path.py +158 -4
- absfuyu/util/performance.py +120 -5
- absfuyu/util/shorten_number.py +1 -1
- absfuyu/util/text_table.py +235 -45
- absfuyu/util/zipped.py +4 -3
- absfuyu/version.py +2 -2
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/METADATA +1 -1
- absfuyu-5.3.0.dist-info/RECORD +76 -0
- absfuyu/core/typings.py +0 -40
- absfuyu-5.1.0.dist-info/RECORD +0 -76
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/WHEEL +0 -0
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/tools/generator.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Generator
|
|
|
3
3
|
------------------
|
|
4
4
|
This generate stuff (Not python's ``generator``)
|
|
5
5
|
|
|
6
|
-
Version: 5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.2.0
|
|
7
|
+
Date updated: 15/03/2025 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Features:
|
|
10
10
|
---------
|
|
@@ -22,12 +22,18 @@ __all__ = ["Charset", "Generator"]
|
|
|
22
22
|
# Library
|
|
23
23
|
# ---------------------------------------------------------------------------
|
|
24
24
|
import string
|
|
25
|
+
from collections.abc import Collection, Sequence
|
|
25
26
|
from itertools import chain, combinations
|
|
26
27
|
from random import choice
|
|
28
|
+
from typing import TypeVar, cast, overload
|
|
27
29
|
|
|
28
|
-
from absfuyu.core import
|
|
29
|
-
from absfuyu.
|
|
30
|
-
from absfuyu.util import
|
|
30
|
+
from absfuyu.core.baseclass import ShowAllMethodsMixin
|
|
31
|
+
from absfuyu.core.docstring import deprecated
|
|
32
|
+
from absfuyu.util import set_min_max
|
|
33
|
+
|
|
34
|
+
# Type
|
|
35
|
+
# ---------------------------------------------------------------------------
|
|
36
|
+
T = TypeVar("T")
|
|
31
37
|
|
|
32
38
|
|
|
33
39
|
# Class
|
|
@@ -37,30 +43,43 @@ class Charset:
|
|
|
37
43
|
Character set data class
|
|
38
44
|
"""
|
|
39
45
|
|
|
40
|
-
DEFAULT = string.ascii_letters + string.digits
|
|
41
|
-
ALPHABET = string.ascii_letters
|
|
42
|
-
FULL = string.ascii_letters + string.digits + string.punctuation
|
|
43
|
-
UPPERCASE = string.ascii_uppercase
|
|
44
|
-
LOWERCASE = string.ascii_lowercase
|
|
45
|
-
DIGIT = string.digits
|
|
46
|
-
SPECIAL = string.punctuation
|
|
47
|
-
ALL = string.printable
|
|
48
|
-
PRODUCT_KEY =
|
|
46
|
+
DEFAULT: str = string.ascii_letters + string.digits
|
|
47
|
+
ALPHABET: str = string.ascii_letters
|
|
48
|
+
FULL: str = string.ascii_letters + string.digits + string.punctuation
|
|
49
|
+
UPPERCASE: str = string.ascii_uppercase
|
|
50
|
+
LOWERCASE: str = string.ascii_lowercase
|
|
51
|
+
DIGIT: str = string.digits
|
|
52
|
+
SPECIAL: str = string.punctuation
|
|
53
|
+
ALL: str = string.printable
|
|
54
|
+
PRODUCT_KEY: str = (
|
|
55
|
+
"BCDFGHJKMNPQRTVWXY2346789" # Charset that various key makers use
|
|
56
|
+
)
|
|
49
57
|
|
|
50
58
|
def __str__(self) -> str:
|
|
51
59
|
charset = [x for x in self.__class__.__dict__.keys() if not x.startswith("__")]
|
|
52
60
|
return f"List of Character set: {charset}"
|
|
53
61
|
|
|
54
62
|
def __repr__(self) -> str:
|
|
55
|
-
|
|
63
|
+
charset = [x for x in self.__class__.__dict__.keys() if not x.startswith("__")]
|
|
64
|
+
clsname = self.__class__.__name__
|
|
65
|
+
return f"{clsname}({', '.join(charset)})"
|
|
56
66
|
|
|
57
67
|
|
|
58
|
-
class Generator(
|
|
68
|
+
class Generator(ShowAllMethodsMixin):
|
|
59
69
|
"""
|
|
60
70
|
Generator that generate stuffs
|
|
71
|
+
|
|
72
|
+
Features:
|
|
73
|
+
---------
|
|
74
|
+
- Generate random string
|
|
75
|
+
- Generate key
|
|
76
|
+
- Generate check digit
|
|
77
|
+
- Generate combinations of list in range
|
|
61
78
|
"""
|
|
62
79
|
|
|
80
|
+
# Generate string
|
|
63
81
|
@staticmethod
|
|
82
|
+
@deprecated("5.2.0", reason="Use generate_string2() instead.")
|
|
64
83
|
def generate_string(
|
|
65
84
|
charset: str = Charset.DEFAULT,
|
|
66
85
|
size: int = 8,
|
|
@@ -69,11 +88,12 @@ class Generator(BaseClass):
|
|
|
69
88
|
string_type_if_1: bool = False,
|
|
70
89
|
):
|
|
71
90
|
"""
|
|
72
|
-
Generate a list of random string from character set (Random string generator)
|
|
91
|
+
Generate a list of random string from character set (Random string generator).
|
|
92
|
+
Deprecated
|
|
73
93
|
|
|
74
94
|
Parameters
|
|
75
95
|
----------
|
|
76
|
-
charset : str
|
|
96
|
+
charset : str, optional
|
|
77
97
|
- Use custom character set or character sets already defined in ``Charset``
|
|
78
98
|
- ``Charset.DEFAULT``: character in [a-zA-Z0-9] (default)
|
|
79
99
|
- ``Charset.ALPHABET``: character in [a-zA-Z]
|
|
@@ -84,21 +104,18 @@ class Generator(BaseClass):
|
|
|
84
104
|
- ``Charset.SPECIAL``: character in [!@#$%^&*()_+=-]
|
|
85
105
|
- ``Charset.ALL``: character in every printable character
|
|
86
106
|
|
|
87
|
-
size : int
|
|
88
|
-
Length of each string in list
|
|
89
|
-
(Default: ``8``)
|
|
107
|
+
size : int, optional
|
|
108
|
+
Length of each string in list, by default ``8``
|
|
90
109
|
|
|
91
|
-
times : int
|
|
92
|
-
How many random string generated
|
|
93
|
-
(Default: ``1``)
|
|
110
|
+
times : int, optional
|
|
111
|
+
How many random string generated, by default ``1``
|
|
94
112
|
|
|
95
|
-
unique : bool
|
|
96
|
-
Each generated text is unique
|
|
97
|
-
(Default: ``False``)
|
|
113
|
+
unique : bool, optional
|
|
114
|
+
Each generated text is unique, by default ``False``
|
|
98
115
|
|
|
99
|
-
string_type_if_1 : bool
|
|
100
|
-
Return a ``str`` type result if ``times == 1
|
|
101
|
-
|
|
116
|
+
string_type_if_1 : bool, optional
|
|
117
|
+
Return a ``str`` type result if ``times == 1``,
|
|
118
|
+
by default ``False``
|
|
102
119
|
|
|
103
120
|
Returns
|
|
104
121
|
-------
|
|
@@ -107,32 +124,18 @@ class Generator(BaseClass):
|
|
|
107
124
|
|
|
108
125
|
str
|
|
109
126
|
When ``string_type_if_1`` is ``True``
|
|
110
|
-
|
|
111
|
-
None
|
|
112
|
-
When invalid option
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Example:
|
|
116
|
-
--------
|
|
117
|
-
>>> Generator.generate_string(times=3)
|
|
118
|
-
['67Xfh1fv', 'iChcGz9P', 'u82fNzlm']
|
|
119
127
|
"""
|
|
120
128
|
|
|
121
129
|
try:
|
|
122
130
|
char_lst = list(charset)
|
|
123
131
|
except Exception:
|
|
124
132
|
char_lst = charset # type: ignore # ! review this sometime
|
|
125
|
-
# logger.debug(char_lst)
|
|
126
133
|
|
|
127
134
|
unique_string = []
|
|
128
135
|
count = 0
|
|
129
|
-
logger.debug(f"Unique generated text: {unique}")
|
|
130
136
|
|
|
131
137
|
while count < times:
|
|
132
138
|
s = "".join(choice(char_lst) for _ in range(size))
|
|
133
|
-
logger.debug(
|
|
134
|
-
f"Time generated: {count + 1}. Remaining: {times - count - 1}. {s}"
|
|
135
|
-
)
|
|
136
139
|
if not unique:
|
|
137
140
|
unique_string.append(s)
|
|
138
141
|
count += 1
|
|
@@ -141,12 +144,127 @@ class Generator(BaseClass):
|
|
|
141
144
|
unique_string.append(s)
|
|
142
145
|
count += 1
|
|
143
146
|
|
|
144
|
-
logger.debug(unique_string)
|
|
145
147
|
if string_type_if_1 and times == 1:
|
|
146
148
|
return unique_string[0]
|
|
147
149
|
else:
|
|
148
150
|
return unique_string
|
|
149
151
|
|
|
152
|
+
@overload
|
|
153
|
+
@staticmethod
|
|
154
|
+
def generate_string2() -> list[str]: ...
|
|
155
|
+
|
|
156
|
+
@overload
|
|
157
|
+
@staticmethod
|
|
158
|
+
def generate_string2(
|
|
159
|
+
charset: str = Charset.DEFAULT,
|
|
160
|
+
length: int = 8,
|
|
161
|
+
times: int = 1,
|
|
162
|
+
unique: bool = False,
|
|
163
|
+
) -> list[str]: ...
|
|
164
|
+
|
|
165
|
+
@overload
|
|
166
|
+
@staticmethod
|
|
167
|
+
def generate_string2(
|
|
168
|
+
charset: Sequence[str],
|
|
169
|
+
length: int = 8,
|
|
170
|
+
times: int = 1,
|
|
171
|
+
unique: bool = False,
|
|
172
|
+
) -> list[str]: ...
|
|
173
|
+
|
|
174
|
+
@staticmethod
|
|
175
|
+
def generate_string2(
|
|
176
|
+
charset: Sequence[str] | Charset | str = Charset.DEFAULT,
|
|
177
|
+
length: int = 8,
|
|
178
|
+
times: int = 1,
|
|
179
|
+
unique: bool = False,
|
|
180
|
+
) -> list[str]:
|
|
181
|
+
"""
|
|
182
|
+
Generate a list of random string from character set (Random string generator).
|
|
183
|
+
Improved version.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
charset : Sequence[str] | Charset | str, optional
|
|
188
|
+
- Use custom character set or character sets already defined in ``Charset``
|
|
189
|
+
- ``Charset.DEFAULT``: character in [a-zA-Z0-9] (default)
|
|
190
|
+
- ``Charset.ALPHABET``: character in [a-zA-Z]
|
|
191
|
+
- ``Charset.FULL``: character in [a-zA-Z0-9] + special characters
|
|
192
|
+
- ``Charset.UPPERCASE``: character in [A-Z]
|
|
193
|
+
- ``Charset.LOWERCASE``: character in [a-z]
|
|
194
|
+
- ``Charset.DIGIT``: character in [0-9]
|
|
195
|
+
- ``Charset.SPECIAL``: character in [!@#$%^&*()_+=-]
|
|
196
|
+
- ``Charset.ALL``: character in every printable character
|
|
197
|
+
|
|
198
|
+
length : int, optional
|
|
199
|
+
Length of each string in list, by default ``8``
|
|
200
|
+
|
|
201
|
+
times : int, optional
|
|
202
|
+
How many random string generated, by default ``1``
|
|
203
|
+
|
|
204
|
+
unique : bool, optional
|
|
205
|
+
Each generated text is unique, by default ``False``
|
|
206
|
+
|
|
207
|
+
Returns
|
|
208
|
+
-------
|
|
209
|
+
list[str]
|
|
210
|
+
List of random generated string.
|
|
211
|
+
|
|
212
|
+
Raises
|
|
213
|
+
------
|
|
214
|
+
TypeError
|
|
215
|
+
When ``charset`` not in correct type.
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
Example:
|
|
219
|
+
--------
|
|
220
|
+
>>> Generator.generate_string2(times=3)
|
|
221
|
+
['67Xfh1fv', 'iChcGz9P', 'u82fNzlm']
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
# Type check
|
|
225
|
+
if isinstance(charset, str):
|
|
226
|
+
character_list: list[str] = list(charset)
|
|
227
|
+
elif isinstance(charset, Sequence):
|
|
228
|
+
character_list = cast(list, charset)
|
|
229
|
+
else:
|
|
230
|
+
raise TypeError("Not a valid type.")
|
|
231
|
+
|
|
232
|
+
# Setup
|
|
233
|
+
generated_strings: list[str] = []
|
|
234
|
+
unique_generated_strings: set[str] = set[str]()
|
|
235
|
+
times_ = max(1, times)
|
|
236
|
+
|
|
237
|
+
while True:
|
|
238
|
+
random_string = "".join(choice(character_list) for _ in range(length))
|
|
239
|
+
if unique:
|
|
240
|
+
unique_generated_strings.add(random_string)
|
|
241
|
+
else:
|
|
242
|
+
generated_strings.append(random_string)
|
|
243
|
+
|
|
244
|
+
# Break condition
|
|
245
|
+
if (
|
|
246
|
+
len(unique_generated_strings) >= times_
|
|
247
|
+
or len(generated_strings) >= times_
|
|
248
|
+
):
|
|
249
|
+
break
|
|
250
|
+
|
|
251
|
+
return list(unique_generated_strings) if unique else generated_strings
|
|
252
|
+
|
|
253
|
+
# Generate key
|
|
254
|
+
@overload
|
|
255
|
+
@classmethod
|
|
256
|
+
def generate_key(cls) -> str: ...
|
|
257
|
+
|
|
258
|
+
@overload
|
|
259
|
+
@classmethod
|
|
260
|
+
def generate_key(
|
|
261
|
+
cls,
|
|
262
|
+
charset: str = Charset.PRODUCT_KEY,
|
|
263
|
+
letter_per_block: int = 5,
|
|
264
|
+
number_of_block: int = 5,
|
|
265
|
+
sep: str = "-",
|
|
266
|
+
) -> str: ...
|
|
267
|
+
|
|
150
268
|
@classmethod
|
|
151
269
|
def generate_key(
|
|
152
270
|
cls,
|
|
@@ -156,25 +274,21 @@ class Generator(BaseClass):
|
|
|
156
274
|
sep: str = "-",
|
|
157
275
|
) -> str:
|
|
158
276
|
"""
|
|
159
|
-
Generate custom key
|
|
277
|
+
Generate custom key.
|
|
160
278
|
|
|
161
279
|
Parameters
|
|
162
280
|
----------
|
|
163
|
-
charset : str
|
|
164
|
-
Character set
|
|
165
|
-
(Default: ``Charset.PRODUCT_KEY``)
|
|
281
|
+
charset : Charset | str, optional
|
|
282
|
+
Character set, by default ``Charset.PRODUCT_KEY``
|
|
166
283
|
|
|
167
|
-
letter_per_block : int
|
|
168
|
-
Number of letter per key block
|
|
169
|
-
(Default: ``5``)
|
|
284
|
+
letter_per_block : int, optional
|
|
285
|
+
Number of letter per key block, by default ``5``
|
|
170
286
|
|
|
171
|
-
number_of_block : int
|
|
172
|
-
Number of key block
|
|
173
|
-
(Default: ``5``)
|
|
287
|
+
number_of_block : int, optional
|
|
288
|
+
Number of key block, by default ``5``
|
|
174
289
|
|
|
175
|
-
sep : str
|
|
176
|
-
Key block separator
|
|
177
|
-
(Default: ``-``)
|
|
290
|
+
sep : str, optional
|
|
291
|
+
Key block separator, by default ``-``
|
|
178
292
|
|
|
179
293
|
Returns
|
|
180
294
|
-------
|
|
@@ -188,36 +302,47 @@ class Generator(BaseClass):
|
|
|
188
302
|
'VKKPJVYD2H-M7R687QCV2'
|
|
189
303
|
"""
|
|
190
304
|
out = sep.join(
|
|
191
|
-
cls.
|
|
305
|
+
cls.generate_string2(
|
|
192
306
|
charset,
|
|
193
|
-
|
|
307
|
+
length=letter_per_block,
|
|
194
308
|
times=number_of_block,
|
|
195
309
|
unique=False,
|
|
196
|
-
string_type_if_1=False,
|
|
197
310
|
)
|
|
198
311
|
)
|
|
199
|
-
logger.debug(out)
|
|
200
312
|
return out
|
|
201
313
|
|
|
314
|
+
# Generate check digit
|
|
315
|
+
@overload
|
|
316
|
+
@staticmethod
|
|
317
|
+
def generate_check_digit(number: int) -> int: ...
|
|
318
|
+
|
|
319
|
+
@overload
|
|
320
|
+
@staticmethod
|
|
321
|
+
def generate_check_digit(number: list[int]) -> int: ...
|
|
322
|
+
|
|
323
|
+
@overload
|
|
202
324
|
@staticmethod
|
|
203
|
-
def generate_check_digit(number:
|
|
325
|
+
def generate_check_digit(number: str) -> int: ...
|
|
326
|
+
|
|
327
|
+
@staticmethod
|
|
328
|
+
def generate_check_digit(number: int | list[int] | str) -> int:
|
|
204
329
|
"""
|
|
205
|
-
Check digit generator
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
330
|
+
Check digit generator.
|
|
331
|
+
|
|
332
|
+
"A check digit is a form of redundancy check used for
|
|
333
|
+
error detection on identification numbers, such as
|
|
334
|
+
bank account numbers, which are used in an application
|
|
335
|
+
where they will at least sometimes be input manually.
|
|
336
|
+
It is analogous to a binary parity bit used to
|
|
337
|
+
check for errors in computer-generated data.
|
|
338
|
+
It consists of one or more digits (or letters) computed
|
|
339
|
+
by an algorithm from the other digits (or letters) in the sequence input.
|
|
340
|
+
With a check digit, one can detect simple errors in
|
|
341
|
+
the input of a series of characters (usually digits)
|
|
342
|
+
such as a single mistyped digit or some permutations
|
|
343
|
+
of two successive digits." (Wikipedia)
|
|
344
|
+
|
|
345
|
+
This function use Luhn's algorithm to calculate.
|
|
221
346
|
|
|
222
347
|
Parameters
|
|
223
348
|
----------
|
|
@@ -232,55 +357,69 @@ class Generator(BaseClass):
|
|
|
232
357
|
|
|
233
358
|
Example:
|
|
234
359
|
--------
|
|
235
|
-
>>> Generator.generate_check_digit(
|
|
360
|
+
>>> Generator.generate_check_digit(4129984562545)
|
|
236
361
|
7
|
|
237
362
|
"""
|
|
238
363
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
364
|
+
# Type handle
|
|
365
|
+
if isinstance(number, int):
|
|
366
|
+
# Turn into list[int] then reverse the order
|
|
367
|
+
num = [int(x) for x in list(str(number))][::-1]
|
|
368
|
+
elif isinstance(number, str):
|
|
369
|
+
num = [int(x) for x in list(number)][::-1]
|
|
370
|
+
elif isinstance(number, list):
|
|
371
|
+
num = number[::-1]
|
|
372
|
+
else:
|
|
373
|
+
raise TypeError("Variable `number` is not correct type.")
|
|
374
|
+
|
|
242
375
|
sum = 0
|
|
243
|
-
|
|
244
|
-
for i in range(len(num)):
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if i % 2 == 0:
|
|
376
|
+
|
|
377
|
+
# for i in range(len(num)):
|
|
378
|
+
for idx, _ in enumerate(num):
|
|
379
|
+
if idx % 2 == 0:
|
|
248
380
|
# double value of the even-th digit
|
|
249
|
-
num[
|
|
381
|
+
num[idx] *= 2
|
|
250
382
|
# sum the character of digit if it's >= 10
|
|
251
|
-
if num[
|
|
252
|
-
num[
|
|
253
|
-
sum += num[
|
|
254
|
-
logger.debug(f"Loop {i + 1}: {num[i]}, {sum}")
|
|
383
|
+
if num[idx] >= 10:
|
|
384
|
+
num[idx] -= 9
|
|
385
|
+
sum += num[idx]
|
|
255
386
|
|
|
256
387
|
out = (10 - (sum % 10)) % 10
|
|
257
|
-
logger.debug(f"Output: {out}")
|
|
258
388
|
return out
|
|
259
389
|
|
|
390
|
+
# Generate combinations range
|
|
391
|
+
@overload
|
|
392
|
+
@staticmethod
|
|
393
|
+
def combinations_range(collection: Collection[T]) -> list[tuple[T, ...]]: ...
|
|
394
|
+
|
|
395
|
+
@overload
|
|
396
|
+
@staticmethod
|
|
397
|
+
def combinations_range(
|
|
398
|
+
collection: Collection[T], *, min_len: int = 1, max_len: int = 0
|
|
399
|
+
) -> list[tuple[T, ...]]: ...
|
|
400
|
+
|
|
260
401
|
@staticmethod
|
|
261
402
|
def combinations_range(
|
|
262
|
-
|
|
263
|
-
) -> list[tuple]:
|
|
403
|
+
collection: Collection[T], *, min_len: int = 1, max_len: int = 0
|
|
404
|
+
) -> list[tuple[T, ...]]:
|
|
264
405
|
"""
|
|
265
|
-
Generate all combinations of a ``
|
|
406
|
+
Generate all combinations of a ``collection`` from ``min_len`` to ``max_len``
|
|
266
407
|
|
|
267
408
|
Parameters
|
|
268
409
|
----------
|
|
269
|
-
|
|
270
|
-
A
|
|
410
|
+
collection : Collection[T]
|
|
411
|
+
A collection (Iterable with ``__len__``) that need to generate combination
|
|
271
412
|
|
|
272
|
-
min_len : int
|
|
273
|
-
Minimum ``r`` of ``combinations``
|
|
274
|
-
(Default: ``1``)
|
|
413
|
+
min_len : int, optional
|
|
414
|
+
Minimum ``r`` of ``combinations``, by default ``1``
|
|
275
415
|
|
|
276
|
-
max_len : int
|
|
277
|
-
Maximum ``r`` of ``combinations``
|
|
278
|
-
(Default: ``0`` - len of ``sequence``)
|
|
416
|
+
max_len : int, optional
|
|
417
|
+
Maximum ``r`` of ``combinations``, by default ``0`` (len of ``collection``)
|
|
279
418
|
|
|
280
419
|
Returns
|
|
281
420
|
-------
|
|
282
421
|
list[tuple]
|
|
283
|
-
A list of all combinations from range(``min_len``, ``max_len``) of ``
|
|
422
|
+
A list of all combinations from range(``min_len``, ``max_len``) of ``collection``
|
|
284
423
|
|
|
285
424
|
|
|
286
425
|
Example:
|
|
@@ -289,15 +428,17 @@ class Generator(BaseClass):
|
|
|
289
428
|
[(1, 2), (1, 3), (2, 3), (1, 2, 3)]
|
|
290
429
|
"""
|
|
291
430
|
# Restrain
|
|
431
|
+
len_iter = len(
|
|
432
|
+
collection
|
|
433
|
+
) # with collection.abc.Iterable, use len(list(collection))
|
|
292
434
|
if max_len < 1:
|
|
293
|
-
max_len =
|
|
294
|
-
max_len = int(
|
|
435
|
+
max_len = len_iter
|
|
436
|
+
max_len = int(min(max_len, len_iter))
|
|
295
437
|
min_len = int(set_min_max(min_len, min_value=1, max_value=max_len))
|
|
296
|
-
logger.debug(f"Combination range: [{min_len}, {max_len}]")
|
|
297
438
|
|
|
298
439
|
# Return
|
|
299
440
|
return list(
|
|
300
441
|
chain.from_iterable(
|
|
301
|
-
|
|
442
|
+
combinations(collection, i) for i in range(min_len, max_len + 1)
|
|
302
443
|
)
|
|
303
444
|
)
|