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