pythonic-fp-circulararray 6.0.3__py3-none-any.whl → 6.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.
- pythonic_fp/circulararray/__init__.py +6 -8
- pythonic_fp/circulararray/auto.py +107 -91
- pythonic_fp/circulararray/fixed.py +112 -95
- {pythonic_fp_circulararray-6.0.3.dist-info → pythonic_fp_circulararray-6.1.0.dist-info}/METADATA +6 -6
- pythonic_fp_circulararray-6.1.0.dist-info/RECORD +11 -0
- pythonic_fp_circulararray-6.0.3.dist-info/RECORD +0 -11
- {pythonic_fp_circulararray-6.0.3.dist-info → pythonic_fp_circulararray-6.1.0.dist-info}/WHEEL +0 -0
- {pythonic_fp_circulararray-6.0.3.dist-info → pythonic_fp_circulararray-6.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,19 +14,17 @@
|
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
16
|
Circular Array
|
|
17
|
-
|
|
17
|
+
==============
|
|
18
18
|
|
|
19
|
-
.. admonition:: Stateful circular array data structures
|
|
19
|
+
.. admonition:: Stateful circular array data structures
|
|
20
20
|
|
|
21
|
-
- O(1) pops and pushes either
|
|
21
|
+
- O(1) pops and pushes on either side
|
|
22
22
|
- O(1) size determination
|
|
23
23
|
- O(1) indexing
|
|
24
|
-
-
|
|
24
|
+
- two types of circular arrays
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- Class constructors ``CA`` and ``CAF`` take an optional iterator to populate circular array.
|
|
29
|
-
- Factory Functions ``ca`` and ``caf`` take a variable number of parameters to populate circular array.
|
|
26
|
+
- fixed capacity: ``CAF``
|
|
27
|
+
- variable capacity: ``CA``
|
|
30
28
|
|
|
31
29
|
"""
|
|
32
30
|
|
|
@@ -12,20 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
16
|
-
.. admonition:: Variable storage capacity circular array CA
|
|
17
|
-
|
|
18
|
-
- O(1) pops either end
|
|
19
|
-
- O(1) amortized pushes either end
|
|
20
|
-
- O(1) indexing, fully supports slicing
|
|
21
|
-
- auto-resizing more storage capacity when necessary, manually compatible
|
|
22
|
-
- iterable, safely mutates while iterators iterating over previous state
|
|
23
|
-
- comparisons compare identity before equality, like builtins
|
|
24
|
-
- in boolean context, falsy when empty, otherwise truthy
|
|
25
|
-
- function ``ca`` produces auto-resizing circular array from arguments
|
|
26
|
-
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
15
|
from collections.abc import Callable, Iterable, Iterator
|
|
30
16
|
from typing import cast, Final, overload
|
|
31
17
|
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
@@ -36,17 +22,31 @@ nada: Final[NoValue] = NoValue()
|
|
|
36
22
|
|
|
37
23
|
|
|
38
24
|
class CA[X]:
|
|
25
|
+
"""
|
|
26
|
+
.. admonition:: Variable storage capacity circular array CA
|
|
27
|
+
|
|
28
|
+
- O(1) pops either end
|
|
29
|
+
- O(1) amortized pushes either end
|
|
30
|
+
- O(1) indexing, fully supports slicing
|
|
31
|
+
- auto-resizing more storage capacity when necessary, manually compatible
|
|
32
|
+
- iterable but not threadsafe
|
|
33
|
+
- comparisons compare identity before equality, like builtins
|
|
34
|
+
- in boolean context, falsy when empty, otherwise truthy
|
|
35
|
+
- function ``ca`` produces auto-resizing circular array from arguments
|
|
36
|
+
|
|
37
|
+
"""
|
|
39
38
|
__slots__ = '_xs', '_cnt', '_cap', '_front', '_rear'
|
|
40
39
|
|
|
41
40
|
def __init__(self, *xs: Iterable[X]) -> None:
|
|
42
41
|
"""
|
|
43
|
-
:param xs:
|
|
44
|
-
|
|
45
|
-
:raises ValueError:
|
|
42
|
+
:param xs: Takes 0 or 1 iterable parameters to initially
|
|
43
|
+
populate the ``CA`` left (front) to right (back).
|
|
44
|
+
:raises ValueError: When more than one iterable is provided.
|
|
45
|
+
:raises TypeError: When passed a non-iterable parameter.
|
|
46
46
|
|
|
47
47
|
"""
|
|
48
48
|
if (size := len(xs)) > 1:
|
|
49
|
-
msg = f'CA expects at most 1
|
|
49
|
+
msg = f'CA expects at most 1 iterable, got {size}'
|
|
50
50
|
raise ValueError(msg)
|
|
51
51
|
if size:
|
|
52
52
|
values: list[X | NoValue] = list(cast(Iterable[X | NoValue], xs[0]))
|
|
@@ -139,6 +139,61 @@ class CA[X]:
|
|
|
139
139
|
+ [nada],
|
|
140
140
|
)
|
|
141
141
|
|
|
142
|
+
def __bool__(self) -> bool:
|
|
143
|
+
return self._cnt > 0
|
|
144
|
+
|
|
145
|
+
def __len__(self) -> int:
|
|
146
|
+
return self._cnt
|
|
147
|
+
|
|
148
|
+
def __eq__(self, other: object) -> bool:
|
|
149
|
+
"""
|
|
150
|
+
.. admonition:: Equality comparison
|
|
151
|
+
|
|
152
|
+
Efficiently compare ``CA`` to another object.
|
|
153
|
+
|
|
154
|
+
:param other: The object to be compared.
|
|
155
|
+
:returns: ``True`` if ``other`` is another ``CA`` whose
|
|
156
|
+
contents compare as equal to the corresponding
|
|
157
|
+
contents of the ``CA``, otherwise ``False``.
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
if self is other:
|
|
161
|
+
return True
|
|
162
|
+
if not isinstance(other, type(self)):
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
(
|
|
166
|
+
front1,
|
|
167
|
+
cnt1,
|
|
168
|
+
capacity1,
|
|
169
|
+
front2,
|
|
170
|
+
cnt2,
|
|
171
|
+
capacity2,
|
|
172
|
+
) = (
|
|
173
|
+
self._front,
|
|
174
|
+
self._cnt,
|
|
175
|
+
self._cap,
|
|
176
|
+
other._front,
|
|
177
|
+
other._cnt,
|
|
178
|
+
other._cap,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if cnt1 != cnt2:
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
for nn in range(cnt1):
|
|
185
|
+
if (
|
|
186
|
+
self._xs[(front1 + nn) % capacity1]
|
|
187
|
+
is other._xs[(front2 + nn) % capacity2]
|
|
188
|
+
):
|
|
189
|
+
continue
|
|
190
|
+
if (
|
|
191
|
+
self._xs[(front1 + nn) % capacity1]
|
|
192
|
+
!= other._xs[(front2 + nn) % capacity2]
|
|
193
|
+
):
|
|
194
|
+
return False
|
|
195
|
+
return True
|
|
196
|
+
|
|
142
197
|
def __iter__(self) -> Iterator[X]:
|
|
143
198
|
if self._cnt > 0:
|
|
144
199
|
(
|
|
@@ -177,26 +232,6 @@ class CA[X]:
|
|
|
177
232
|
position = (position - 1) % capacity
|
|
178
233
|
yield cast(X, current_state[position])
|
|
179
234
|
|
|
180
|
-
def __repr__(self) -> str:
|
|
181
|
-
"""
|
|
182
|
-
:returns: String of the form ``ca(x1, x2, ..., xn)``.
|
|
183
|
-
|
|
184
|
-
"""
|
|
185
|
-
return 'ca(' + ', '.join(map(repr, self)) + ')'
|
|
186
|
-
|
|
187
|
-
def __str__(self) -> str:
|
|
188
|
-
"""
|
|
189
|
-
:returns: String of the form ``(|x1, x2, ..., xn|)``.
|
|
190
|
-
|
|
191
|
-
"""
|
|
192
|
-
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
193
|
-
|
|
194
|
-
def __bool__(self) -> bool:
|
|
195
|
-
return self._cnt > 0
|
|
196
|
-
|
|
197
|
-
def __len__(self) -> int:
|
|
198
|
-
return self._cnt
|
|
199
|
-
|
|
200
235
|
@overload
|
|
201
236
|
def __getitem__(self, idx: int) -> X: ...
|
|
202
237
|
@overload
|
|
@@ -289,50 +324,31 @@ class CA[X]:
|
|
|
289
324
|
)
|
|
290
325
|
del _ca
|
|
291
326
|
|
|
292
|
-
def
|
|
327
|
+
def __repr__(self) -> str:
|
|
293
328
|
"""
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
329
|
+
.. admonition:: String representation
|
|
330
|
+
|
|
331
|
+
Return 'CA("repr(x1)", "repr(x2)", ..., "repr(xn)")'
|
|
332
|
+
where x1, x2, ..., xn are the circular array's
|
|
333
|
+
contents and "repr(xi)" is the repr-string for xi.
|
|
334
|
+
|
|
335
|
+
:returns: A string to reproduce the ``CA``.
|
|
298
336
|
|
|
299
337
|
"""
|
|
300
|
-
|
|
301
|
-
return True
|
|
302
|
-
if not isinstance(other, type(self)):
|
|
303
|
-
return False
|
|
338
|
+
return 'ca(' + ', '.join(map(repr, self)) + ')'
|
|
304
339
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
capacity1,
|
|
309
|
-
front2,
|
|
310
|
-
cnt2,
|
|
311
|
-
capacity2,
|
|
312
|
-
) = (
|
|
313
|
-
self._front,
|
|
314
|
-
self._cnt,
|
|
315
|
-
self._cap,
|
|
316
|
-
other._front,
|
|
317
|
-
other._cnt,
|
|
318
|
-
other._cap,
|
|
319
|
-
)
|
|
340
|
+
def __str__(self) -> str:
|
|
341
|
+
r"""
|
|
342
|
+
.. admonition:: User string
|
|
320
343
|
|
|
321
|
-
|
|
322
|
-
|
|
344
|
+
Return string '(\| x1, x2, ..., xn \|)'
|
|
345
|
+
where x1, x2, ..., xn are the circular array's
|
|
346
|
+
contents displayed as strings.
|
|
323
347
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
):
|
|
329
|
-
continue
|
|
330
|
-
if (
|
|
331
|
-
self._xs[(front1 + nn) % capacity1]
|
|
332
|
-
!= other._xs[(front2 + nn) % capacity2]
|
|
333
|
-
):
|
|
334
|
-
return False
|
|
335
|
-
return True
|
|
348
|
+
:returns: A string meaningful to an end user.
|
|
349
|
+
|
|
350
|
+
"""
|
|
351
|
+
return '(| ' + ', '.join(map(str, self)) + ' |)'
|
|
336
352
|
|
|
337
353
|
def pushl(self, *xs: X) -> None:
|
|
338
354
|
"""
|
|
@@ -344,7 +360,7 @@ class CA[X]:
|
|
|
344
360
|
:param xs: Items to be pushed onto the front of the circular array from the left.
|
|
345
361
|
|
|
346
362
|
"""
|
|
347
|
-
for
|
|
363
|
+
for x in xs:
|
|
348
364
|
if self._cnt == self._cap:
|
|
349
365
|
self._double_storage_capacity()
|
|
350
366
|
(
|
|
@@ -353,7 +369,7 @@ class CA[X]:
|
|
|
353
369
|
self._cnt,
|
|
354
370
|
) = (
|
|
355
371
|
(self._front - 1) % self._cap,
|
|
356
|
-
|
|
372
|
+
x,
|
|
357
373
|
self._cnt + 1,
|
|
358
374
|
)
|
|
359
375
|
|
|
@@ -392,7 +408,7 @@ class CA[X]:
|
|
|
392
408
|
"""
|
|
393
409
|
if self._cnt > 1:
|
|
394
410
|
(
|
|
395
|
-
|
|
411
|
+
x,
|
|
396
412
|
self._xs[self._front],
|
|
397
413
|
self._front,
|
|
398
414
|
self._cnt,
|
|
@@ -404,7 +420,7 @@ class CA[X]:
|
|
|
404
420
|
)
|
|
405
421
|
elif self._cnt == 1:
|
|
406
422
|
(
|
|
407
|
-
|
|
423
|
+
x,
|
|
408
424
|
self._xs[self._front],
|
|
409
425
|
self._cnt,
|
|
410
426
|
self._front,
|
|
@@ -419,7 +435,7 @@ class CA[X]:
|
|
|
419
435
|
else:
|
|
420
436
|
msg = 'Method popl called on an empty CA'
|
|
421
437
|
raise ValueError(msg)
|
|
422
|
-
return cast(X,
|
|
438
|
+
return cast(X, x)
|
|
423
439
|
|
|
424
440
|
def popr(self) -> X:
|
|
425
441
|
"""
|
|
@@ -433,7 +449,7 @@ class CA[X]:
|
|
|
433
449
|
"""
|
|
434
450
|
if self._cnt > 1:
|
|
435
451
|
(
|
|
436
|
-
|
|
452
|
+
x,
|
|
437
453
|
self._xs[self._rear],
|
|
438
454
|
self._rear,
|
|
439
455
|
self._cnt,
|
|
@@ -445,7 +461,7 @@ class CA[X]:
|
|
|
445
461
|
)
|
|
446
462
|
elif self._cnt == 1:
|
|
447
463
|
(
|
|
448
|
-
|
|
464
|
+
x,
|
|
449
465
|
self._xs[self._front],
|
|
450
466
|
self._cnt,
|
|
451
467
|
self._front,
|
|
@@ -460,7 +476,7 @@ class CA[X]:
|
|
|
460
476
|
else:
|
|
461
477
|
msg = 'Method popr called on an empty CA'
|
|
462
478
|
raise ValueError(msg)
|
|
463
|
-
return cast(X,
|
|
479
|
+
return cast(X, x)
|
|
464
480
|
|
|
465
481
|
def popld(self, default: X) -> X:
|
|
466
482
|
"""
|
|
@@ -506,17 +522,17 @@ class CA[X]:
|
|
|
506
522
|
:returns: A ``tuple`` of the items popped, left to right.
|
|
507
523
|
|
|
508
524
|
"""
|
|
509
|
-
|
|
525
|
+
xs: list[X] = []
|
|
510
526
|
|
|
511
527
|
while maximum > 0:
|
|
512
528
|
try:
|
|
513
|
-
|
|
529
|
+
xs.append(self.popl())
|
|
514
530
|
except ValueError:
|
|
515
531
|
break
|
|
516
532
|
else:
|
|
517
533
|
maximum -= 1
|
|
518
534
|
|
|
519
|
-
return tuple(
|
|
535
|
+
return tuple(xs)
|
|
520
536
|
|
|
521
537
|
def poprt(self, maximum: int) -> tuple[X, ...]:
|
|
522
538
|
"""
|
|
@@ -610,8 +626,8 @@ class CA[X]:
|
|
|
610
626
|
return acc
|
|
611
627
|
|
|
612
628
|
acc = cast(L, start)
|
|
613
|
-
for
|
|
614
|
-
acc = f(acc,
|
|
629
|
+
for x in self:
|
|
630
|
+
acc = f(acc, x)
|
|
615
631
|
return acc
|
|
616
632
|
|
|
617
633
|
@overload
|
|
@@ -644,8 +660,8 @@ class CA[X]:
|
|
|
644
660
|
return acc
|
|
645
661
|
|
|
646
662
|
acc = cast(R, start)
|
|
647
|
-
for
|
|
648
|
-
acc = f(
|
|
663
|
+
for x in reversed(self):
|
|
664
|
+
acc = f(x, acc)
|
|
649
665
|
return acc
|
|
650
666
|
|
|
651
667
|
def capacity(self) -> int:
|
|
@@ -12,19 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
16
|
-
.. admonition:: Fixed storage capacity circular array CAF
|
|
17
|
-
|
|
18
|
-
- O(1) pops and pushes either end
|
|
19
|
-
- O(1) indexing, does not support slicing
|
|
20
|
-
- fixed total storage capacity
|
|
21
|
-
- iterable, safely mutates while iterators iterating over previous state
|
|
22
|
-
- comparisons compare identity before equality, like builtins
|
|
23
|
-
- in boolean context, falsy when either empty or full, otherwise truthy
|
|
24
|
-
- function ``caf`` produces fixed capacity circular array from arguments
|
|
25
|
-
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
15
|
from collections.abc import Callable, Iterable, Iterator
|
|
29
16
|
from typing import cast, Final, overload
|
|
30
17
|
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
@@ -35,19 +22,33 @@ nada: Final[NoValue] = NoValue()
|
|
|
35
22
|
|
|
36
23
|
|
|
37
24
|
class CAF[X]:
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
.. admonition:: Fixed storage capacity circular array CAF
|
|
28
|
+
|
|
29
|
+
- O(1) pops and pushes either end
|
|
30
|
+
- O(1) indexing, does not support slicing
|
|
31
|
+
- fixed total storage capacity
|
|
32
|
+
- iterable but not threadsafe
|
|
33
|
+
- comparisons compare identity before equality, like builtins
|
|
34
|
+
- in boolean context, falsy when either empty or full, otherwise truthy
|
|
35
|
+
- function ``caf`` produces fixed capacity circular array from arguments
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
38
|
__slots__ = '_xs', '_cnt', '_cap', '_front', '_rear'
|
|
39
39
|
|
|
40
40
|
def __init__(self, *xs: Iterable[X], cap: int = 2) -> None:
|
|
41
41
|
"""
|
|
42
|
-
:param xs:
|
|
42
|
+
:param xs: Takes 0 or 1 iterable parameters to initially
|
|
43
|
+
populate the ``CAF`` left (front) to right (back).
|
|
43
44
|
:param cap: Minimum fixed storage capacity of circular array.
|
|
44
|
-
:raises
|
|
45
|
-
:raises
|
|
45
|
+
:raises ValueError: When more than one iterable is provided.
|
|
46
|
+
:raises TypeError: When passed a non-iterable positional parameter.
|
|
46
47
|
|
|
47
48
|
"""
|
|
48
49
|
cap = max(2, cap)
|
|
49
50
|
if (size := len(xs)) > 1:
|
|
50
|
-
msg = f'CAF expects at most 1
|
|
51
|
+
msg = f'CAF expects at most 1 iterable, got {size}'
|
|
51
52
|
raise ValueError(msg)
|
|
52
53
|
if size:
|
|
53
54
|
values: list[X | NoValue] = list(cast(Iterable[X | NoValue], xs[0]))
|
|
@@ -66,6 +67,61 @@ class CAF[X]:
|
|
|
66
67
|
self._front = 0
|
|
67
68
|
self._rear = cnt - 1
|
|
68
69
|
|
|
70
|
+
def __bool__(self) -> bool:
|
|
71
|
+
return 0 < self._cnt < self._cap
|
|
72
|
+
|
|
73
|
+
def __len__(self) -> int:
|
|
74
|
+
return self._cnt
|
|
75
|
+
|
|
76
|
+
def __eq__(self, other: object) -> bool:
|
|
77
|
+
"""
|
|
78
|
+
.. admonition:: Equality comparison
|
|
79
|
+
|
|
80
|
+
Efficiently compare ``CAF`` to another object.
|
|
81
|
+
|
|
82
|
+
:param other: The object to be compared.
|
|
83
|
+
:returns: ``True`` if ``other`` is another ``CAF`` whose
|
|
84
|
+
contents compare as equal to the corresponding
|
|
85
|
+
contents of the ``CAF``, otherwise ``False``.
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
if self is other:
|
|
89
|
+
return True
|
|
90
|
+
if not isinstance(other, type(self)):
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
(
|
|
94
|
+
front1,
|
|
95
|
+
cnt1,
|
|
96
|
+
cap1,
|
|
97
|
+
front2,
|
|
98
|
+
cnt2,
|
|
99
|
+
cap2,
|
|
100
|
+
) = (
|
|
101
|
+
self._front,
|
|
102
|
+
self._cnt,
|
|
103
|
+
self._cap,
|
|
104
|
+
other._front,
|
|
105
|
+
other._cnt,
|
|
106
|
+
other._cap,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if cnt1 != cnt2:
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
for nn in range(cnt1):
|
|
113
|
+
if (
|
|
114
|
+
self._xs[(front1 + nn) % cap1]
|
|
115
|
+
is other._xs[(front2 + nn) % cap2]
|
|
116
|
+
):
|
|
117
|
+
continue
|
|
118
|
+
if (
|
|
119
|
+
self._xs[(front1 + nn) % cap1]
|
|
120
|
+
!= other._xs[(front2 + nn) % cap2]
|
|
121
|
+
):
|
|
122
|
+
return False
|
|
123
|
+
return True
|
|
124
|
+
|
|
69
125
|
def __iter__(self) -> Iterator[X]:
|
|
70
126
|
if self._cnt > 0:
|
|
71
127
|
(
|
|
@@ -104,26 +160,6 @@ class CAF[X]:
|
|
|
104
160
|
position = (position - 1) % cap
|
|
105
161
|
yield cast(X, current_state[position])
|
|
106
162
|
|
|
107
|
-
def __repr__(self) -> str:
|
|
108
|
-
"""
|
|
109
|
-
:returns: String of the form ``caf(x1, x2, ..., xn)``.
|
|
110
|
-
|
|
111
|
-
"""
|
|
112
|
-
return 'caf(' + ', '.join(map(repr, self)) + ')'
|
|
113
|
-
|
|
114
|
-
def __str__(self) -> str:
|
|
115
|
-
"""
|
|
116
|
-
:returns: String of the form ``(|x1, x2, ..., xn|)``.
|
|
117
|
-
|
|
118
|
-
"""
|
|
119
|
-
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
120
|
-
|
|
121
|
-
def __bool__(self) -> bool:
|
|
122
|
-
return 0 < self._cnt < self._cap
|
|
123
|
-
|
|
124
|
-
def __len__(self) -> int:
|
|
125
|
-
return self._cnt
|
|
126
|
-
|
|
127
163
|
def __getitem__(self, idx: int) -> X:
|
|
128
164
|
cnt = self._cnt
|
|
129
165
|
if 0 <= idx < cnt:
|
|
@@ -173,52 +209,33 @@ class CAF[X]:
|
|
|
173
209
|
)
|
|
174
210
|
del _ca
|
|
175
211
|
|
|
176
|
-
def
|
|
212
|
+
def __repr__(self) -> str:
|
|
177
213
|
"""
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
214
|
+
.. admonition:: String representation
|
|
215
|
+
|
|
216
|
+
Return 'CAF("repr(x1)", "repr(x2)", ..., "repr(xn)")'
|
|
217
|
+
where x1, x2, ..., xn are the circular array's
|
|
218
|
+
contents and "repr(xi)" is the repr-string for xi.
|
|
219
|
+
|
|
220
|
+
:returns: A string to reproduce the ``CAF``.
|
|
182
221
|
|
|
183
222
|
"""
|
|
184
|
-
|
|
185
|
-
return True
|
|
186
|
-
if not isinstance(other, type(self)):
|
|
187
|
-
return False
|
|
223
|
+
return 'caf(' + ', '.join(map(repr, self)) + ')'
|
|
188
224
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
cap1,
|
|
193
|
-
front2,
|
|
194
|
-
cnt2,
|
|
195
|
-
cap2,
|
|
196
|
-
) = (
|
|
197
|
-
self._front,
|
|
198
|
-
self._cnt,
|
|
199
|
-
self._cap,
|
|
200
|
-
other._front,
|
|
201
|
-
other._cnt,
|
|
202
|
-
other._cap,
|
|
203
|
-
)
|
|
225
|
+
def __str__(self) -> str:
|
|
226
|
+
r"""
|
|
227
|
+
.. admonition:: User string
|
|
204
228
|
|
|
205
|
-
|
|
206
|
-
|
|
229
|
+
Return '(\|x1, x2, ..., xn\|)'
|
|
230
|
+
where x1, x2, ..., xn are the circular array's
|
|
231
|
+
contents displayed as strings.
|
|
207
232
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
):
|
|
213
|
-
continue
|
|
214
|
-
if (
|
|
215
|
-
self._xs[(front1 + nn) % cap1]
|
|
216
|
-
!= other._xs[(front2 + nn) % cap2]
|
|
217
|
-
):
|
|
218
|
-
return False
|
|
219
|
-
return True
|
|
233
|
+
:returns: A string meaningful to an end user.
|
|
234
|
+
|
|
235
|
+
"""
|
|
236
|
+
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
220
237
|
|
|
221
|
-
def pushl(self,
|
|
238
|
+
def pushl(self, x: X) -> None:
|
|
222
239
|
"""
|
|
223
240
|
.. admonition:: Push left
|
|
224
241
|
|
|
@@ -238,11 +255,11 @@ class CAF[X]:
|
|
|
238
255
|
self._cnt,
|
|
239
256
|
) = (
|
|
240
257
|
(self._front - 1) % self._cap,
|
|
241
|
-
|
|
258
|
+
x,
|
|
242
259
|
self._cnt + 1,
|
|
243
260
|
)
|
|
244
261
|
|
|
245
|
-
def pushr(self,
|
|
262
|
+
def pushr(self, x: X) -> None:
|
|
246
263
|
"""
|
|
247
264
|
.. admonition:: Push right
|
|
248
265
|
|
|
@@ -262,7 +279,7 @@ class CAF[X]:
|
|
|
262
279
|
self._cnt,
|
|
263
280
|
) = (
|
|
264
281
|
(self._rear + 1) % self._cap,
|
|
265
|
-
|
|
282
|
+
x,
|
|
266
283
|
self._cnt + 1,
|
|
267
284
|
)
|
|
268
285
|
|
|
@@ -278,7 +295,7 @@ class CAF[X]:
|
|
|
278
295
|
"""
|
|
279
296
|
if self._cnt > 1:
|
|
280
297
|
(
|
|
281
|
-
|
|
298
|
+
x,
|
|
282
299
|
self._xs[self._front],
|
|
283
300
|
self._front,
|
|
284
301
|
self._cnt,
|
|
@@ -290,7 +307,7 @@ class CAF[X]:
|
|
|
290
307
|
)
|
|
291
308
|
elif self._cnt == 1:
|
|
292
309
|
(
|
|
293
|
-
|
|
310
|
+
x,
|
|
294
311
|
self._xs[self._front],
|
|
295
312
|
self._cnt,
|
|
296
313
|
self._front,
|
|
@@ -305,7 +322,7 @@ class CAF[X]:
|
|
|
305
322
|
else:
|
|
306
323
|
msg = 'Method popl called on an empty CAF'
|
|
307
324
|
raise ValueError(msg)
|
|
308
|
-
return cast(X,
|
|
325
|
+
return cast(X, x)
|
|
309
326
|
|
|
310
327
|
def popr(self) -> X:
|
|
311
328
|
"""
|
|
@@ -319,7 +336,7 @@ class CAF[X]:
|
|
|
319
336
|
"""
|
|
320
337
|
if self._cnt > 1:
|
|
321
338
|
(
|
|
322
|
-
|
|
339
|
+
x,
|
|
323
340
|
self._xs[self._rear],
|
|
324
341
|
self._rear,
|
|
325
342
|
self._cnt,
|
|
@@ -331,7 +348,7 @@ class CAF[X]:
|
|
|
331
348
|
)
|
|
332
349
|
elif self._cnt == 1:
|
|
333
350
|
(
|
|
334
|
-
|
|
351
|
+
x,
|
|
335
352
|
self._xs[self._front],
|
|
336
353
|
self._cnt,
|
|
337
354
|
self._front,
|
|
@@ -346,7 +363,7 @@ class CAF[X]:
|
|
|
346
363
|
else:
|
|
347
364
|
msg = 'Method popr called on an empty CAF'
|
|
348
365
|
raise ValueError(msg)
|
|
349
|
-
return cast(X,
|
|
366
|
+
return cast(X, x)
|
|
350
367
|
|
|
351
368
|
def popld(self, default: X) -> X:
|
|
352
369
|
"""
|
|
@@ -392,17 +409,17 @@ class CAF[X]:
|
|
|
392
409
|
:returns: A ``tuple`` of the items popped, left to right.
|
|
393
410
|
|
|
394
411
|
"""
|
|
395
|
-
|
|
412
|
+
xs: list[X] = []
|
|
396
413
|
|
|
397
414
|
while maximum > 0:
|
|
398
415
|
try:
|
|
399
|
-
|
|
416
|
+
xs.append(self.popl())
|
|
400
417
|
except ValueError:
|
|
401
418
|
break
|
|
402
419
|
else:
|
|
403
420
|
maximum -= 1
|
|
404
421
|
|
|
405
|
-
return tuple(
|
|
422
|
+
return tuple(xs)
|
|
406
423
|
|
|
407
424
|
def poprt(self, maximum: int) -> tuple[X, ...]:
|
|
408
425
|
"""
|
|
@@ -414,15 +431,15 @@ class CAF[X]:
|
|
|
414
431
|
:returns: A ``tuple`` of the items popped, right to left.
|
|
415
432
|
|
|
416
433
|
"""
|
|
417
|
-
|
|
434
|
+
xs: list[X] = []
|
|
418
435
|
while maximum > 0:
|
|
419
436
|
try:
|
|
420
|
-
|
|
437
|
+
xs.append(self.popr())
|
|
421
438
|
except ValueError:
|
|
422
439
|
break
|
|
423
440
|
else:
|
|
424
441
|
maximum -= 1
|
|
425
|
-
return tuple(
|
|
442
|
+
return tuple(xs)
|
|
426
443
|
|
|
427
444
|
def rotl(self, n: int = 1) -> None:
|
|
428
445
|
"""
|
|
@@ -496,8 +513,8 @@ class CAF[X]:
|
|
|
496
513
|
return acc
|
|
497
514
|
|
|
498
515
|
acc = cast(L, start)
|
|
499
|
-
for
|
|
500
|
-
acc = f(acc,
|
|
516
|
+
for x in self:
|
|
517
|
+
acc = f(acc, x)
|
|
501
518
|
return acc
|
|
502
519
|
|
|
503
520
|
@overload
|
|
@@ -530,8 +547,8 @@ class CAF[X]:
|
|
|
530
547
|
return acc
|
|
531
548
|
|
|
532
549
|
acc = cast(R, start)
|
|
533
|
-
for
|
|
534
|
-
acc = f(
|
|
550
|
+
for x in reversed(self):
|
|
551
|
+
acc = f(x, acc)
|
|
535
552
|
return acc
|
|
536
553
|
|
|
537
554
|
def capacity(self) -> int:
|
{pythonic_fp_circulararray-6.0.3.dist-info → pythonic_fp_circulararray-6.1.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythonic-fp-circulararray
|
|
3
|
-
Version: 6.0
|
|
3
|
+
Version: 6.1.0
|
|
4
4
|
Summary: Circular Array
|
|
5
5
|
Keywords: auto resizing,circular array,circulararray,dequeue,indexable,pop,push
|
|
6
6
|
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
@@ -17,8 +17,8 @@ License-File: LICENSE
|
|
|
17
17
|
Requires-Dist: pythonic-fp-gadgets>=4.0.2
|
|
18
18
|
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
19
19
|
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-circulararray/blob/main/CHANGELOG.rst
|
|
20
|
-
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/circulararray
|
|
21
|
-
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/
|
|
20
|
+
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/projects/circulararray.html
|
|
21
|
+
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/
|
|
22
22
|
Project-URL: Source, https://github.com/grscheller/pythonic-fp-circulararray
|
|
23
23
|
Provides-Extra: test
|
|
24
24
|
|
|
@@ -54,15 +54,15 @@ Python module implementing stateful circular array data structures.
|
|
|
54
54
|
|
|
55
55
|
Part of the
|
|
56
56
|
`pythonic-fp
|
|
57
|
-
<https://grscheller.github.io/pythonic-fp
|
|
57
|
+
<https://grscheller.github.io/pythonic-fp/>`_
|
|
58
58
|
PyPI projects.
|
|
59
59
|
|
|
60
60
|
Documentation
|
|
61
61
|
-------------
|
|
62
62
|
|
|
63
|
-
Documentation for this project
|
|
63
|
+
Documentation and other links for this project are hosted on
|
|
64
64
|
`GitHub Pages
|
|
65
|
-
<https://grscheller.github.io/pythonic-fp
|
|
65
|
+
<https://grscheller.github.io/pythonic-fp/projects/circulararray.html>`_.
|
|
66
66
|
|
|
67
67
|
Copyright and License
|
|
68
68
|
---------------------
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
pythonic_fp/circulararray/__init__.py,sha256=PJsikfFReHq2QXpmcg_AYeBbuyauGjfJ9bBdc2YNtzo,1016
|
|
2
|
+
pythonic_fp/circulararray/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
pythonic_fp/circulararray/auto.py,sha256=HNi_xbjITgqMYx-ReqzFSkd3CViPLvLky83PnUVJm94,21669
|
|
4
|
+
pythonic_fp/circulararray/auto.pyi,sha256=kSJ3b7tleHTZIWy3QmYPTmJJ54xNb4lC8ipNBhtyGsA,1786
|
|
5
|
+
pythonic_fp/circulararray/fixed.py,sha256=XyoQFIRCzxDWMBSb1CRWzjYhlsQmFNSG58ZxmRjgtJg,17647
|
|
6
|
+
pythonic_fp/circulararray/fixed.pyi,sha256=SUtEp8QWNKwJKJ5PzqL3MIuAHfAkIJU1Dy_BlqaWb48,1503
|
|
7
|
+
pythonic_fp/circulararray/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
pythonic_fp_circulararray-6.1.0.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
9
|
+
pythonic_fp_circulararray-6.1.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
10
|
+
pythonic_fp_circulararray-6.1.0.dist-info/METADATA,sha256=XzABxLHhGc6NYy5INTWSOuSe67Hn5EaSH3dBMl2ghyI,2699
|
|
11
|
+
pythonic_fp_circulararray-6.1.0.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
pythonic_fp/circulararray/__init__.py,sha256=MYPgNiLNoBf84VldZ7r0iszP13kaG0AxJF3pOOUETJg,1193
|
|
2
|
-
pythonic_fp/circulararray/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
pythonic_fp/circulararray/auto.py,sha256=u7PPffiRhCs3EXDkH65REi0ZYGLEnEgOf7NT8RQHQ5c,21119
|
|
4
|
-
pythonic_fp/circulararray/auto.pyi,sha256=kSJ3b7tleHTZIWy3QmYPTmJJ54xNb4lC8ipNBhtyGsA,1786
|
|
5
|
-
pythonic_fp/circulararray/fixed.py,sha256=SJ6vlp0g3NlTAwWRk3PPTtA8uoJlg0kMg5JCBg13Ji0,17125
|
|
6
|
-
pythonic_fp/circulararray/fixed.pyi,sha256=SUtEp8QWNKwJKJ5PzqL3MIuAHfAkIJU1Dy_BlqaWb48,1503
|
|
7
|
-
pythonic_fp/circulararray/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
pythonic_fp_circulararray-6.0.3.dist-info/licenses/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
|
|
9
|
-
pythonic_fp_circulararray-6.0.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
10
|
-
pythonic_fp_circulararray-6.0.3.dist-info/METADATA,sha256=uWOl3wbd0dRLcYDz-OLpg-yuCVQyPqyw_eEGjIb0c2M,2697
|
|
11
|
-
pythonic_fp_circulararray-6.0.3.dist-info/RECORD,,
|
{pythonic_fp_circulararray-6.0.3.dist-info → pythonic_fp_circulararray-6.1.0.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|