Skip to content

Commit aaf9dc1

Browse files
committed
-
1 parent ea67b7d commit aaf9dc1

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

source_py3/python_toolbox/binary_search/binary_search_profile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class BinarySearchProfile:
2828
'''
2929

3030
def __init__(self, sequence, value, function=misc_tools.identity_function,
31-
both=None):
31+
*, both=None):
3232
'''
3333
Construct a `BinarySearchProfile`.
3434

source_py3/python_toolbox/caching/cached_property.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def _get_personality(self):
2929
personality = CachedProperty(_get_personality)
3030
3131
You can also put in a value as the first argument if you'd like to have it
32-
returned instead of using a getter. (It can be a tobag static value like
32+
returned instead of using a getter. (It can be a totally static value like
3333
`0`). If this value happens to be a callable but you'd still like it to be
3434
used as a static value, use `force_value_not_getter=True`.
3535
'''

source_py3/python_toolbox/combi/perming/calculating_length.py

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
from python_toolbox import nifty_collections
77

88

9-
###############################################################################
10-
119
_length_of_recurrent_perm_space_cache = {}
1210

1311
def calculate_length_of_recurrent_perm_space(k, fbb):
@@ -26,18 +24,40 @@ def calculate_length_of_recurrent_perm_space(k, fbb):
2624
cache = _length_of_recurrent_perm_space_cache
2725
if not isinstance(fbb, nifty_collections.FrozenBagBag):
2826
fbb = nifty_collections.FrozenBagBag(fbb)
27+
### Checking for edge cases: ##############################################
28+
# #
2929
if k == 0:
3030
return 1
3131
elif k == 1:
3232
assert fbb
33-
# (Works because `FrozenBagBag` has a functioning `__bool__`,
34-
# unlike Python's `Counter`.)
33+
# (Works because `FrozenBagBag` has a functioning `__bool__`, unlike
34+
# Python's `Counter`.)
3535
return fbb.n_elements
36+
# #
37+
### Finished checking for edge cases. #####################################
38+
3639
try:
3740
return cache[(k, fbb)]
3841
except KeyError:
3942
pass
43+
44+
# This is a 2-phase algorithm, similar to recursion but not really
45+
# recursion since we don't want to abuse the stack.
46+
#
47+
# In the first phase, we get all the sub-FBBs that we need to solve for to
48+
# get a solution for this FBB, and then for these sub-FBBs we get the
49+
# sub-sub-FBBs we need to solve in order to solve them, and we continue
50+
# until we reach trivial FBBs.
51+
#
52+
# In the second phase, we'll go over the levels of FBBs, starting with the
53+
# simplest ones and making our way up to the original FBB. The simplest
54+
# FBBs will be solved trivially, and then as they get progressively more
55+
# complex, each FBB will be solved using the solutions of its sub-FBB.
56+
# Every solution will be stored in the global cache.
57+
4058

59+
### Doing phase one, getting all sub-FBBs: ################################
60+
# #
4161
levels = []
4262
current_fbbs = {fbb}
4363
while len(levels) < k and current_fbbs:
@@ -47,8 +67,11 @@ def calculate_length_of_recurrent_perm_space(k, fbb):
4767
for fbb_ in current_fbbs if (k_, fbb_) not in cache}
4868
)
4969
current_fbbs = set(itertools.chain(*levels[-1].values()))
50-
51-
# The last level is calculated. Time to make our way up.
70+
# #
71+
### Finished doing phase one, getting all sub-FBBs. #######################
72+
73+
### Doing phase two, solving FBBs from trivial to complex: ################
74+
# #
5275
for k_, level in enumerate(reversed(levels), (k - len(levels) + 1)):
5376
if k_ == 1:
5477
for fbb_, sub_fbb_bag in level.items():
@@ -59,6 +82,8 @@ def calculate_length_of_recurrent_perm_space(k, fbb):
5982
(cache[(k_ - 1, sub_fbb)] * factor for
6083
sub_fbb, factor in sub_fbb_bag.items())
6184
)
85+
# #
86+
### Finished doing phase two, solving FBBs from trivial to complex. #######
6287

6388
return cache[(k, fbb)]
6489

@@ -84,18 +109,40 @@ def calculate_length_of_recurrent_comb_space(k, fbb):
84109
cache = _length_of_recurrent_comb_space_cache
85110
if not isinstance(fbb, nifty_collections.FrozenBagBag):
86111
fbb = nifty_collections.FrozenBagBag(fbb)
112+
### Checking for edge cases: ##############################################
113+
# #
87114
if k == 0:
88115
return 1
89116
elif k == 1:
90117
assert fbb
91118
# (Works because `FrozenBagBag` has a functioning `__bool__`,
92119
# unlike Python's `Counter`.)
93120
return fbb.n_elements
121+
# #
122+
### Finished checking for edge cases. #####################################
123+
94124
try:
95125
return cache[(k, fbb)]
96126
except KeyError:
97127
pass
98128

129+
# This is a 2-phase algorithm, similar to recursion but not really
130+
# recursion since we don't want to abuse the stack.
131+
#
132+
# In the first phase, we get all the sub-FBBs that we need to solve for to
133+
# get a solution for this FBB, and then for these sub-FBBs we get the
134+
# sub-sub-FBBs we need to solve in order to solve them, and we continue
135+
# until we reach trivial FBBs.
136+
#
137+
# In the second phase, we'll go over the levels of FBBs, starting with the
138+
# simplest ones and making our way up to the original FBB. The simplest
139+
# FBBs will be solved trivially, and then as they get progressively more
140+
# complex, each FBB will be solved using the solutions of its sub-FBB.
141+
# Every solution will be stored in the global cache.
142+
143+
144+
### Doing phase one, getting all sub-FBBs: ################################
145+
# #
99146
levels = []
100147
current_fbbs = {fbb}
101148
while len(levels) < k and current_fbbs:
@@ -105,8 +152,11 @@ def calculate_length_of_recurrent_comb_space(k, fbb):
105152
for fbb_ in current_fbbs if (k_, fbb_) not in cache}
106153
)
107154
current_fbbs = set(itertools.chain(*levels[-1].values()))
155+
# #
156+
### Finished doing phase one, getting all sub-FBBs. #######################
108157

109-
# The last level is calculated. Time to make our way up.
158+
### Doing phase two, solving FBBs from trivial to complex: ################
159+
# #
110160
for k_, level in enumerate(reversed(levels), (k - len(levels) + 1)):
111161
if k_ == 1:
112162
for fbb_, sub_fbbs in level.items():
@@ -116,6 +166,8 @@ def calculate_length_of_recurrent_comb_space(k, fbb):
116166
cache[(k_, fbb_)] = sum(
117167
(cache[(k_ - 1, sub_fbb)] for sub_fbb in sub_fbbs)
118168
)
169+
# #
170+
### Finished doing phase two, solving FBBs from trivial to complex. #######
119171

120172
return cache[(k, fbb)]
121173

0 commit comments

Comments
 (0)