pythonstl 1.1.4__tar.gz → 1.1.5__tar.gz
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.
- {pythonstl-1.1.4 → pythonstl-1.1.5}/PKG-INFO +3 -3
- {pythonstl-1.1.4 → pythonstl-1.1.5}/README.md +1 -1
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pyproject.toml +2 -2
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/__init__.py +1 -1
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/algorithms.py +330 -331
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/map.py +1 -2
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/priority_queue.py +1 -2
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/queue.py +1 -2
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/set.py +3 -4
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/stack.py +1 -2
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/vector.py +2 -3
- {pythonstl-1.1.4 → pythonstl-1.1.5}/.flake8 +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/.github/FUNDING.yml +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/.github/workflows/python.yml +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/.gitignore +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/Cargo.lock +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/Cargo.toml +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/LICENSE +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/PUBLISHING.md +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/README.md +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_algorithms.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_all_structures.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_binary_search.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_map.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_native.cpp +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_rust_vs_py.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_stack.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/benchmarks/benchmark_vector.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/example_usage.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/mypy.ini +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/_rust.pdb +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/core/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/core/base.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/core/exceptions.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/core/iterator.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/facade/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/associative/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/associative/_map_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/associative/_set_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/heaps/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/heaps/_priority_queue_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/linear/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/linear/_queue_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/linear/_stack_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/pythonstl/implementations/linear/_vector_impl.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/setup.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/src/lib.rs +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/__init__.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_algorithms.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_binary_search.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_map.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_priority_queue.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_queue.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_set.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_stack.py +0 -0
- {pythonstl-1.1.4 → pythonstl-1.1.5}/tests/test_vector.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonstl
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.5
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -15,7 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
|
15
15
|
License-File: LICENSE
|
|
16
16
|
Summary: C++ STL-style containers implemented in Python using the Facade Design Pattern
|
|
17
17
|
Keywords: stl,data-structures,containers,facade-pattern,cpp-stl,standard-template-library
|
|
18
|
-
Author-email: PySTL Contributors <
|
|
18
|
+
Author-email: PySTL Contributors <anshsoni702@gmail.com>
|
|
19
19
|
License: MIT
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
21
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
@@ -445,5 +445,5 @@ Contributions are welcome! Please:
|
|
|
445
445
|
- GitHub: [@AnshMNSoni](https://github.com/AnshMNSoni)
|
|
446
446
|
- Issues: [GitHub Issues](https://github.com/AnshMNSoni/PythonSTL/issues)
|
|
447
447
|
|
|
448
|
-
**PythonSTL
|
|
448
|
+
**PythonSTL v1.1.5** - Bringing C++ STL elegance to Python
|
|
449
449
|
|
|
@@ -419,4 +419,4 @@ Contributions are welcome! Please:
|
|
|
419
419
|
- GitHub: [@AnshMNSoni](https://github.com/AnshMNSoni)
|
|
420
420
|
- Issues: [GitHub Issues](https://github.com/AnshMNSoni/PythonSTL/issues)
|
|
421
421
|
|
|
422
|
-
**PythonSTL
|
|
422
|
+
**PythonSTL v1.1.5** - Bringing C++ STL elegance to Python
|
|
@@ -8,11 +8,11 @@ module-name = "pythonstl._rust"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "pythonstl"
|
|
11
|
-
version = "1.1.
|
|
11
|
+
version = "1.1.5"
|
|
12
12
|
description = "C++ STL-style containers implemented in Python using the Facade Design Pattern"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
authors = [
|
|
15
|
-
{name = "PySTL Contributors", email = "
|
|
15
|
+
{name = "PySTL Contributors", email = "anshsoni702@gmail.com"}
|
|
16
16
|
]
|
|
17
17
|
license = {text = "MIT"}
|
|
18
18
|
classifiers = [
|
|
@@ -8,7 +8,7 @@ This package provides clean, STL-compliant interfaces for common
|
|
|
8
8
|
data structures while hiding implementation details from users.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
__version__ = "1.1.
|
|
11
|
+
__version__ = "1.1.5"
|
|
12
12
|
__author__ = "PySTL Contributors"
|
|
13
13
|
|
|
14
14
|
from pythonstl.facade.stack import stack
|
|
@@ -1,331 +1,330 @@
|
|
|
1
|
-
"""
|
|
2
|
-
C++ STL Algorithms Suite.
|
|
3
|
-
|
|
4
|
-
This module provides replicas of standard C++ algorithms from <algorithm>
|
|
5
|
-
with dynamic Rust backend loading and in-place list mutation.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from typing import Callable, Any
|
|
9
|
-
|
|
10
|
-
try:
|
|
11
|
-
from pythonstl._rust import next_permutation as _rust_next_permutation
|
|
12
|
-
from pythonstl._rust import prev_permutation as _rust_prev_permutation
|
|
13
|
-
from pythonstl._rust import nth_element as _rust_nth_element
|
|
14
|
-
from pythonstl._rust import partition as _rust_partition
|
|
15
|
-
from pythonstl._rust import lower_bound as _rust_lower_bound
|
|
16
|
-
from pythonstl._rust import upper_bound as _rust_upper_bound
|
|
17
|
-
from pythonstl._rust import binary_search as _rust_binary_search
|
|
18
|
-
from pythonstl._rust import equal_range as _rust_equal_range
|
|
19
|
-
RUST_AVAILABLE = True
|
|
20
|
-
except ImportError:
|
|
21
|
-
RUST_AVAILABLE = False
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# ----------------- Pure-Python Fallbacks -----------------
|
|
25
|
-
|
|
26
|
-
def _py_next_permutation(arr: list) -> bool:
|
|
27
|
-
n = len(arr)
|
|
28
|
-
if n <= 1:
|
|
29
|
-
return False
|
|
30
|
-
|
|
31
|
-
i = n - 2
|
|
32
|
-
while i >= 0 and arr[i] >= arr[i + 1]:
|
|
33
|
-
i -= 1
|
|
34
|
-
|
|
35
|
-
if i < 0:
|
|
36
|
-
arr.reverse()
|
|
37
|
-
return False
|
|
38
|
-
|
|
39
|
-
j = n - 1
|
|
40
|
-
while arr[j] <= arr[i]:
|
|
41
|
-
j -= 1
|
|
42
|
-
|
|
43
|
-
arr[i], arr[j] = arr[j], arr[i]
|
|
44
|
-
arr[i + 1:] = reversed(arr[i + 1:])
|
|
45
|
-
return True
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def _py_prev_permutation(arr: list) -> bool:
|
|
49
|
-
n = len(arr)
|
|
50
|
-
if n <= 1:
|
|
51
|
-
return False
|
|
52
|
-
|
|
53
|
-
i = n - 2
|
|
54
|
-
while i >= 0 and arr[i] <= arr[i + 1]:
|
|
55
|
-
i -= 1
|
|
56
|
-
|
|
57
|
-
if i < 0:
|
|
58
|
-
arr.reverse()
|
|
59
|
-
return False
|
|
60
|
-
|
|
61
|
-
j = n - 1
|
|
62
|
-
while arr[j] >= arr[i]:
|
|
63
|
-
j -= 1
|
|
64
|
-
|
|
65
|
-
arr[i], arr[j] = arr[j], arr[i]
|
|
66
|
-
arr[i + 1:] = reversed(arr[i + 1:])
|
|
67
|
-
return True
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def _py_nth_element(arr: list, nth: int) -> None:
|
|
71
|
-
n = len(arr)
|
|
72
|
-
if nth < 0 or nth >= n:
|
|
73
|
-
return
|
|
74
|
-
|
|
75
|
-
left = 0
|
|
76
|
-
right = n - 1
|
|
77
|
-
while left < right:
|
|
78
|
-
mid = left + (right - left) // 2
|
|
79
|
-
arr[mid], arr[right] = arr[right], arr[mid]
|
|
80
|
-
pivot = arr[right]
|
|
81
|
-
i = left
|
|
82
|
-
for j in range(left, right):
|
|
83
|
-
if arr[j] < pivot:
|
|
84
|
-
arr[i], arr[j] = arr[j], arr[i]
|
|
85
|
-
i += 1
|
|
86
|
-
arr[i], arr[right] = arr[right], arr[i]
|
|
87
|
-
|
|
88
|
-
pivot_idx = i
|
|
89
|
-
if pivot_idx == nth:
|
|
90
|
-
return
|
|
91
|
-
elif pivot_idx > nth:
|
|
92
|
-
right = pivot_idx - 1
|
|
93
|
-
else:
|
|
94
|
-
left = pivot_idx + 1
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
idx
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
All elements
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
'
|
|
329
|
-
'
|
|
330
|
-
|
|
331
|
-
]
|
|
1
|
+
"""
|
|
2
|
+
C++ STL Algorithms Suite.
|
|
3
|
+
|
|
4
|
+
This module provides replicas of standard C++ algorithms from <algorithm>
|
|
5
|
+
with dynamic Rust backend loading and in-place list mutation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Callable, Any
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from pythonstl._rust import next_permutation as _rust_next_permutation
|
|
12
|
+
from pythonstl._rust import prev_permutation as _rust_prev_permutation
|
|
13
|
+
from pythonstl._rust import nth_element as _rust_nth_element
|
|
14
|
+
from pythonstl._rust import partition as _rust_partition
|
|
15
|
+
from pythonstl._rust import lower_bound as _rust_lower_bound
|
|
16
|
+
from pythonstl._rust import upper_bound as _rust_upper_bound
|
|
17
|
+
from pythonstl._rust import binary_search as _rust_binary_search
|
|
18
|
+
from pythonstl._rust import equal_range as _rust_equal_range
|
|
19
|
+
RUST_AVAILABLE = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
RUST_AVAILABLE = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ----------------- Pure-Python Fallbacks -----------------
|
|
25
|
+
|
|
26
|
+
def _py_next_permutation(arr: list) -> bool:
|
|
27
|
+
n = len(arr)
|
|
28
|
+
if n <= 1:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
i = n - 2
|
|
32
|
+
while i >= 0 and arr[i] >= arr[i + 1]:
|
|
33
|
+
i -= 1
|
|
34
|
+
|
|
35
|
+
if i < 0:
|
|
36
|
+
arr.reverse()
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
j = n - 1
|
|
40
|
+
while arr[j] <= arr[i]:
|
|
41
|
+
j -= 1
|
|
42
|
+
|
|
43
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
44
|
+
arr[i + 1:] = reversed(arr[i + 1:])
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _py_prev_permutation(arr: list) -> bool:
|
|
49
|
+
n = len(arr)
|
|
50
|
+
if n <= 1:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
i = n - 2
|
|
54
|
+
while i >= 0 and arr[i] <= arr[i + 1]:
|
|
55
|
+
i -= 1
|
|
56
|
+
|
|
57
|
+
if i < 0:
|
|
58
|
+
arr.reverse()
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
j = n - 1
|
|
62
|
+
while arr[j] >= arr[i]:
|
|
63
|
+
j -= 1
|
|
64
|
+
|
|
65
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
66
|
+
arr[i + 1:] = reversed(arr[i + 1:])
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _py_nth_element(arr: list, nth: int) -> None:
|
|
71
|
+
n = len(arr)
|
|
72
|
+
if nth < 0 or nth >= n:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
left = 0
|
|
76
|
+
right = n - 1
|
|
77
|
+
while left < right:
|
|
78
|
+
mid = left + (right - left) // 2
|
|
79
|
+
arr[mid], arr[right] = arr[right], arr[mid]
|
|
80
|
+
pivot = arr[right]
|
|
81
|
+
i = left
|
|
82
|
+
for j in range(left, right):
|
|
83
|
+
if arr[j] < pivot:
|
|
84
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
85
|
+
i += 1
|
|
86
|
+
arr[i], arr[right] = arr[right], arr[i]
|
|
87
|
+
|
|
88
|
+
pivot_idx = i
|
|
89
|
+
if pivot_idx == nth:
|
|
90
|
+
return
|
|
91
|
+
elif pivot_idx > nth:
|
|
92
|
+
right = pivot_idx - 1
|
|
93
|
+
else:
|
|
94
|
+
left = pivot_idx + 1
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _py_partition(arr: list, predicate: Callable[[Any], bool]) -> int:
|
|
98
|
+
i = 0
|
|
99
|
+
for j in range(len(arr)):
|
|
100
|
+
if predicate(arr[j]):
|
|
101
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
102
|
+
i += 1
|
|
103
|
+
return i
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _py_lower_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> int:
|
|
107
|
+
left = 0
|
|
108
|
+
right = len(arr)
|
|
109
|
+
while left < right:
|
|
110
|
+
mid = left + (right - left) // 2
|
|
111
|
+
mid_val = arr[mid]
|
|
112
|
+
is_less = comp(mid_val, val) if comp else (mid_val < val)
|
|
113
|
+
if is_less:
|
|
114
|
+
left = mid + 1
|
|
115
|
+
else:
|
|
116
|
+
right = mid
|
|
117
|
+
return left
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _py_upper_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> int:
|
|
121
|
+
left = 0
|
|
122
|
+
right = len(arr)
|
|
123
|
+
while left < right:
|
|
124
|
+
mid = left + (right - left) // 2
|
|
125
|
+
mid_val = arr[mid]
|
|
126
|
+
is_less = comp(val, mid_val) if comp else (val < mid_val)
|
|
127
|
+
if is_less:
|
|
128
|
+
right = mid
|
|
129
|
+
else:
|
|
130
|
+
left = mid + 1
|
|
131
|
+
return left
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _py_binary_search(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> bool:
|
|
135
|
+
if not arr:
|
|
136
|
+
return False
|
|
137
|
+
idx = _py_lower_bound(arr, val, comp)
|
|
138
|
+
if idx < len(arr):
|
|
139
|
+
elem = arr[idx]
|
|
140
|
+
if comp:
|
|
141
|
+
return not comp(elem, val) and not comp(val, elem)
|
|
142
|
+
return elem == val
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _py_equal_range(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> tuple[int, int]:
|
|
147
|
+
return _py_lower_bound(arr, val, comp), _py_upper_bound(arr, val, comp)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ----------------- Public API Interfaces -----------------
|
|
151
|
+
|
|
152
|
+
def next_permutation(arr: list, use_rust: bool = True) -> bool:
|
|
153
|
+
"""
|
|
154
|
+
Rearranges elements in-place to the next lexicographically greater permutation.
|
|
155
|
+
|
|
156
|
+
If the next permutation exists, rearranges elements and returns True.
|
|
157
|
+
Otherwise, reverses the array to the smallest ascending order and returns False.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
arr: The list to modify in-place.
|
|
161
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
True if next permutation exists, False otherwise.
|
|
165
|
+
|
|
166
|
+
Time Complexity:
|
|
167
|
+
O(n) where n is len(arr)
|
|
168
|
+
"""
|
|
169
|
+
if use_rust and RUST_AVAILABLE:
|
|
170
|
+
return _rust_next_permutation(arr)
|
|
171
|
+
return _py_next_permutation(arr)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def prev_permutation(arr: list, use_rust: bool = True) -> bool:
|
|
175
|
+
"""
|
|
176
|
+
Rearranges elements in-place to the next lexicographically smaller permutation.
|
|
177
|
+
|
|
178
|
+
If the previous permutation exists, rearranges elements and returns True.
|
|
179
|
+
Otherwise, reverses the array to the largest descending order and returns False.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
arr: The list to modify in-place.
|
|
183
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
True if prev permutation exists, False otherwise.
|
|
187
|
+
|
|
188
|
+
Time Complexity:
|
|
189
|
+
O(n) where n is len(arr)
|
|
190
|
+
"""
|
|
191
|
+
if use_rust and RUST_AVAILABLE:
|
|
192
|
+
return _rust_prev_permutation(arr)
|
|
193
|
+
return _py_prev_permutation(arr)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def nth_element(arr: list, nth: int, use_rust: bool = True) -> None:
|
|
197
|
+
"""
|
|
198
|
+
Partitions the list in-place so that the element at index `nth` is the one
|
|
199
|
+
that would be there if the list were completely sorted.
|
|
200
|
+
|
|
201
|
+
All elements preceding `nth` are partitioned to be less than or equal to `nth`.
|
|
202
|
+
All elements succeeding `nth` are partitioned to be greater than or equal to `nth`.
|
|
203
|
+
Does not guarantee sorted order of the surrounding elements.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
arr: The list to modify in-place.
|
|
207
|
+
nth: The index that should contain the sorted element.
|
|
208
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
209
|
+
|
|
210
|
+
Time Complexity:
|
|
211
|
+
O(n) average case
|
|
212
|
+
"""
|
|
213
|
+
if use_rust and RUST_AVAILABLE:
|
|
214
|
+
_rust_nth_element(arr, nth)
|
|
215
|
+
else:
|
|
216
|
+
_py_nth_element(arr, nth)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def partition(arr: list, predicate: Callable[[Any], bool], use_rust: bool = True) -> int:
|
|
220
|
+
"""
|
|
221
|
+
Reorders the elements in the list in-place such that all elements for which
|
|
222
|
+
`predicate` returns True precede all elements for which it returns False.
|
|
223
|
+
|
|
224
|
+
Does not guarantee stable relative ordering.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
arr: The list to modify in-place.
|
|
228
|
+
predicate: A callable returning True or False for each element.
|
|
229
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
The boundary index pointing to the first element that returned False.
|
|
233
|
+
|
|
234
|
+
Time Complexity:
|
|
235
|
+
O(n) where n is len(arr)
|
|
236
|
+
"""
|
|
237
|
+
if use_rust and RUST_AVAILABLE:
|
|
238
|
+
return _rust_partition(arr, predicate)
|
|
239
|
+
return _py_partition(arr, predicate)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def lower_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> int:
|
|
243
|
+
"""
|
|
244
|
+
Returns the index of the first element in the range that does not compare less than `val`.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
arr: The sorted list to search.
|
|
248
|
+
val: The value to search for.
|
|
249
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
250
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
The index of the first element that is >= val, or len(arr) if not found.
|
|
254
|
+
|
|
255
|
+
Time Complexity:
|
|
256
|
+
O(log n)
|
|
257
|
+
"""
|
|
258
|
+
if use_rust and RUST_AVAILABLE:
|
|
259
|
+
return _rust_lower_bound(arr, val, comp)
|
|
260
|
+
return _py_lower_bound(arr, val, comp)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def upper_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> int:
|
|
264
|
+
"""
|
|
265
|
+
Returns the index of the first element in the range that compares greater than `val`.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
arr: The sorted list to search.
|
|
269
|
+
val: The value to search for.
|
|
270
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
271
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
The index of the first element that is > val, or len(arr) if not found.
|
|
275
|
+
|
|
276
|
+
Time Complexity:
|
|
277
|
+
O(log n)
|
|
278
|
+
"""
|
|
279
|
+
if use_rust and RUST_AVAILABLE:
|
|
280
|
+
return _rust_upper_bound(arr, val, comp)
|
|
281
|
+
return _py_upper_bound(arr, val, comp)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def binary_search(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> bool:
|
|
285
|
+
"""
|
|
286
|
+
Checks if a value is present in the sorted range.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
arr: The sorted list to search.
|
|
290
|
+
val: The value to search for.
|
|
291
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
292
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
True if the element equivalent to val is found, False otherwise.
|
|
296
|
+
|
|
297
|
+
Time Complexity:
|
|
298
|
+
O(log n)
|
|
299
|
+
"""
|
|
300
|
+
if use_rust and RUST_AVAILABLE:
|
|
301
|
+
return _rust_binary_search(arr, val, comp)
|
|
302
|
+
return _py_binary_search(arr, val, comp)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def equal_range(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> tuple[int, int]:
|
|
306
|
+
"""
|
|
307
|
+
Returns the range of elements equivalent to a given value.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
arr: The sorted list to search.
|
|
311
|
+
val: The value to search for.
|
|
312
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
313
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
314
|
+
|
|
315
|
+
Returns:
|
|
316
|
+
A tuple (lower_bound_index, upper_bound_index) defining the range of equivalent elements.
|
|
317
|
+
|
|
318
|
+
Time Complexity:
|
|
319
|
+
O(log n)
|
|
320
|
+
"""
|
|
321
|
+
if use_rust and RUST_AVAILABLE:
|
|
322
|
+
return _rust_equal_range(arr, val, comp)
|
|
323
|
+
return _py_equal_range(arr, val, comp)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
__all__ = [
|
|
327
|
+
'next_permutation', 'prev_permutation', 'nth_element', 'partition',
|
|
328
|
+
'lower_bound', 'upper_bound', 'binary_search', 'equal_range',
|
|
329
|
+
'RUST_AVAILABLE'
|
|
330
|
+
]
|
|
@@ -248,7 +248,7 @@ class stl_map:
|
|
|
248
248
|
"""
|
|
249
249
|
if not isinstance(other, stl_map):
|
|
250
250
|
return False
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
self_data = dict(self._impl.get_data()) if self._is_rust else self._impl._data
|
|
253
253
|
other_data = dict(other._impl.get_data()) if other._is_rust else other._impl._data
|
|
254
254
|
return self_data == other_data
|
|
@@ -294,5 +294,4 @@ class stl_map:
|
|
|
294
294
|
return new_map
|
|
295
295
|
|
|
296
296
|
|
|
297
|
-
|
|
298
297
|
__all__ = ['stl_map']
|
|
@@ -191,7 +191,7 @@ class priority_queue:
|
|
|
191
191
|
return False
|
|
192
192
|
if self._comparator != other._comparator:
|
|
193
193
|
return False
|
|
194
|
-
|
|
194
|
+
|
|
195
195
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
196
196
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
197
197
|
return self_data == other_data
|
|
@@ -224,5 +224,4 @@ class priority_queue:
|
|
|
224
224
|
return new_pq
|
|
225
225
|
|
|
226
226
|
|
|
227
|
-
|
|
228
227
|
__all__ = ['priority_queue']
|
|
@@ -197,7 +197,7 @@ class queue:
|
|
|
197
197
|
"""
|
|
198
198
|
if not isinstance(other, queue):
|
|
199
199
|
return False
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
202
202
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
203
203
|
return self_data == other_data
|
|
@@ -230,5 +230,4 @@ class queue:
|
|
|
230
230
|
return new_queue
|
|
231
231
|
|
|
232
232
|
|
|
233
|
-
|
|
234
233
|
__all__ = ['queue']
|
|
@@ -218,14 +218,14 @@ class stl_set:
|
|
|
218
218
|
"""
|
|
219
219
|
if not isinstance(other, stl_set):
|
|
220
220
|
return False
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
223
223
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
224
|
-
|
|
224
|
+
|
|
225
225
|
# BTreeSet elements are sorted, so direct list equality works for sorted comparison
|
|
226
226
|
if self._is_rust and other._is_rust:
|
|
227
227
|
return self_data == other_data
|
|
228
|
-
|
|
228
|
+
|
|
229
229
|
return set(self_data) == set(other_data)
|
|
230
230
|
|
|
231
231
|
def __iter__(self) -> TypingIterator[T]:
|
|
@@ -267,5 +267,4 @@ class stl_set:
|
|
|
267
267
|
return new_set
|
|
268
268
|
|
|
269
269
|
|
|
270
|
-
|
|
271
270
|
__all__ = ['stl_set']
|
|
@@ -180,7 +180,7 @@ class stack:
|
|
|
180
180
|
"""
|
|
181
181
|
if not isinstance(other, stack):
|
|
182
182
|
return False
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
185
185
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
186
186
|
return self_data == other_data
|
|
@@ -213,5 +213,4 @@ class stack:
|
|
|
213
213
|
return new_stack
|
|
214
214
|
|
|
215
215
|
|
|
216
|
-
|
|
217
216
|
__all__ = ['stack']
|
|
@@ -336,7 +336,7 @@ class vector:
|
|
|
336
336
|
"""
|
|
337
337
|
if not isinstance(other, vector):
|
|
338
338
|
return False
|
|
339
|
-
|
|
339
|
+
|
|
340
340
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
341
341
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
342
342
|
return self_data == other_data
|
|
@@ -353,7 +353,7 @@ class vector:
|
|
|
353
353
|
"""
|
|
354
354
|
self_data = self._impl.get_data() if self._is_rust else self._impl._data
|
|
355
355
|
other_data = other._impl.get_data() if other._is_rust else other._impl._data
|
|
356
|
-
|
|
356
|
+
|
|
357
357
|
min_size = min(len(self_data), len(other_data))
|
|
358
358
|
for i in range(min_size):
|
|
359
359
|
if self_data[i] < other_data[i]:
|
|
@@ -402,5 +402,4 @@ class vector:
|
|
|
402
402
|
return new_vector
|
|
403
403
|
|
|
404
404
|
|
|
405
|
-
|
|
406
405
|
__all__ = ['vector']
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|