Skip to content

Commit 5dbfa72

Browse files
committed
-
1 parent d5baa68 commit 5dbfa72

File tree

5 files changed

+75
-4
lines changed

5 files changed

+75
-4
lines changed

source_py3/python_toolbox/combi/perm.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,35 @@ def number(self):
203203
self.just_dapplied_rapplied_perm_space.n_unused_elements)
204204

205205

206+
is_infinite = caching.CachedProperty(
207+
lambda self: self.just_dapplied_rapplied_perm_space.is_infinite
208+
)
209+
206210
@caching.CachedProperty
207211
@nifty_collections.LazyTuple.factory()
208212
def _perm_sequence(self):
209213
assert (0 <= self.number <
210214
self.just_dapplied_rapplied_perm_space.length)
215+
n_digits_pad = 0 if self.is_infinite else self.length
211216
factoradic_number = math_tools.to_factoradic(
212217
self.number * math.factorial(
213218
self.just_dapplied_rapplied_perm_space.n_unused_elements),
214-
n_digits_pad=self.just_dapplied_rapplied_perm_space.sequence_length
219+
n_digits_pad=n_digits_pad
215220
)
216221
if self.is_partial:
222+
assert not self.is_infinite
217223
factoradic_number = factoradic_number[
218224
:-self.just_dapplied_rapplied_perm_space.n_unused_elements
219225
]
220226
unused_numbers = list(self.just_dapplied_rapplied_perm_space.sequence,)
221227
result = tuple(unused_numbers.pop(factoradic_digit) for
222228
factoradic_digit in factoradic_number)
229+
if self.is_infinite:
230+
from .chain_space import ChainSpace
231+
result = ChainSpace((
232+
result,
233+
sequence_tools.CuteRange(len(result), infinity)
234+
))
223235
assert len(result) == self.length
224236
return result
225237

source_py3/python_toolbox/combi/perm_space.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,11 @@ def _coerce_perm(self, perm):
902902
return Perm(perm, self)
903903

904904

905+
is_infinite = caching.CachedProperty(
906+
lambda self: self.sequence_length == infinity
907+
)
908+
909+
905910
infinite_pure_perm_space = PermSpace(infinity)
906911

907912

source_py3/python_toolbox/math_tools/factorials.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import math
55
import collections
66
import itertools
7+
import numbers
78

89
infinity = float('inf')
910
infinities = (infinity, -infinity)
@@ -85,7 +86,7 @@ def from_factoradic(factoradic_number):
8586
return number
8687

8788

88-
def to_factoradic(number, n_digits_pad=None):
89+
def to_factoradic(number, n_digits_pad=0):
8990
'''
9091
Convert a number to factoradic representation (in a tuple.)
9192
@@ -106,6 +107,7 @@ def to_factoradic(number, n_digits_pad=None):
106107
'''
107108
assert isinstance(number, int)
108109
assert number >= 0
110+
assert isinstance(n_digits_pad, numbers.Integral)
109111
n_digits = inverse_factorial(number, round_up=False) + 1
110112
digits = [None] * n_digits
111113
current_number = number
@@ -114,7 +116,7 @@ def to_factoradic(number, n_digits_pad=None):
114116
digits[n_digits - i - 1], current_number = \
115117
divmod(current_number, unit)
116118
result = tuple(digits)
117-
if n_digits_pad and (len(result) < n_digits_pad):
119+
if (len(result) < n_digits_pad):
118120
return ((0,) * (n_digits_pad - len(result))) + result
119121
else:
120122
return result
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11

22
from .misc import *
3-
from .cute_range import CuteRange
3+
from .cute_range import CuteRange
4+
from .sequence_view import SequenceView
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import abc
2+
import builtins
3+
import types
4+
import collections
5+
import numbers
6+
7+
from python_toolbox import caching
8+
9+
from .misc import CuteSequence
10+
11+
infinity = float('inf')
12+
infinities = (infinity, -infinity)
13+
14+
15+
class SequenceView(CuteSequence):
16+
def __init__(self, sequence, indices=None):
17+
self.sequence = sequence
18+
if indices is not None:
19+
self.indices = indices
20+
21+
indices = caching.CachedProperty(
22+
lambda self: list(range(len(self.sequence))))
23+
24+
def __getitem__(self, index):
25+
return self.sequence[self.indices[index]]
26+
27+
def __iter__(self):
28+
yield from map(self.sequence.__getitem__, self.indices)
29+
30+
__contains__ = lambda self: any(item == value for value in self)
31+
32+
def __reversed__(self):
33+
yield from map(self.sequence.__getitem__, reversed(self.indices))
34+
35+
# Can't defined `index` which uses the wrapped sequence's `index` because
36+
# `index` stops on the first occurrence, and if our first occurrence was
37+
# removed, we'd need to search for the next one.
38+
39+
def _nopity_nope_nope(self, item):
40+
raise TypeError("Can't add stuff to a `VirtualPopper`")
41+
extend = insert = append = _nopity_nope_nope
42+
43+
clear = lambda self: self.sequence.clear()
44+
copy = lambda self: type(self)(self.sequence, indices=self.indices)
45+
reverse = lambda self: self.indices.reverse()
46+
47+
# This are the money methods right here:
48+
pop = lambda self, i: self.sequence[self.indices.pop(i)]
49+
remove = lambda self, item: self.indices.remove(self.sequence.index(item))
50+
51+

0 commit comments

Comments
 (0)