mapFolding 0.16.4__py3-none-any.whl → 0.17.1__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.
- easyRun/NOTcountingFolds.py +28 -11
- easyRun/__init__.py +1 -0
- easyRun/countFolds.py +16 -2
- easyRun/eliminateFolds.py +60 -0
- easyRun/meanders.py +3 -3
- mapFolding/__init__.py +2 -1
- mapFolding/_theTypes.py +0 -1
- mapFolding/algorithms/A086345.py +8 -3
- mapFolding/algorithms/__init__.py +1 -1
- mapFolding/algorithms/constraintPropagation.py +184 -0
- mapFolding/algorithms/elimination.py +131 -0
- mapFolding/algorithms/eliminationCount.py +26 -0
- mapFolding/algorithms/eliminationPinned.py +35 -0
- mapFolding/algorithms/iff.py +206 -0
- mapFolding/algorithms/matrixMeanders.py +59 -18
- mapFolding/algorithms/matrixMeandersNumPyndas.py +841 -0
- mapFolding/algorithms/patternFinder.py +280 -0
- mapFolding/algorithms/pinning2Dn.py +345 -0
- mapFolding/algorithms/pinning2DnAnnex.py +43 -0
- mapFolding/algorithms/symmetricFolds.py +24 -25
- mapFolding/basecamp.py +84 -14
- mapFolding/beDRY.py +14 -1
- mapFolding/dataBaskets.py +86 -71
- mapFolding/reference/irvineJavaPort.py +3 -3
- mapFolding/reference/meandersDumpingGround/matrixMeandersNumPyV1finalForm.py +1 -1
- mapFolding/someAssemblyRequired/A007822/_asynchronousAnnex.py +1 -1
- mapFolding/someAssemblyRequired/A007822/makeA007822AsynchronousModules.py +5 -3
- mapFolding/someAssemblyRequired/A007822/makeA007822Modules.py +22 -6
- mapFolding/someAssemblyRequired/RecipeJob.py +14 -24
- mapFolding/someAssemblyRequired/__init__.py +1 -0
- mapFolding/someAssemblyRequired/_toolkitContainers.py +6 -4
- mapFolding/someAssemblyRequired/infoBooth.py +2 -1
- mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +75 -20
- mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +9 -10
- mapFolding/someAssemblyRequired/makingModules_count.py +20 -22
- mapFolding/someAssemblyRequired/makingModules_doTheNeedful.py +9 -9
- mapFolding/someAssemblyRequired/mapFoldingModules/makeMapFoldingModules.py +6 -5
- mapFolding/someAssemblyRequired/meanders/makeMeandersModules.py +6 -6
- mapFolding/someAssemblyRequired/toolkitMakeModules.py +3 -29
- mapFolding/someAssemblyRequired/toolkitNumba.py +2 -1
- mapFolding/someAssemblyRequired/transformationTools.py +2 -3
- mapFolding/syntheticModules/A007822/algorithm.py +8 -8
- mapFolding/syntheticModules/A007822/asynchronous.py +12 -13
- mapFolding/syntheticModules/A007822/initializeState.py +10 -8
- mapFolding/syntheticModules/A007822/theorem2.py +10 -8
- mapFolding/syntheticModules/A007822/theorem2Numba.py +20 -16
- mapFolding/syntheticModules/A007822/theorem2Trimmed.py +10 -8
- mapFolding/syntheticModules/countParallelNumba.py +5 -2
- mapFolding/syntheticModules/daoOfMapFoldingNumba.py +4 -2
- mapFolding/syntheticModules/initializeState.py +1 -1
- mapFolding/syntheticModules/meanders/bigInt.py +52 -15
- mapFolding/syntheticModules/theorem2.py +1 -1
- mapFolding/syntheticModules/theorem2Numba.py +4 -2
- mapFolding/syntheticModules/theorem2Trimmed.py +1 -1
- mapFolding/tests/conftest.py +1 -1
- mapFolding/tests/test_computations.py +21 -4
- mapFolding/tests/verify.py +323 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/METADATA +14 -11
- mapfolding-0.17.1.dist-info/RECORD +112 -0
- easyRun/A000682.py +0 -25
- easyRun/A005316.py +0 -20
- mapFolding/algorithms/matrixMeandersBeDry.py +0 -182
- mapFolding/algorithms/matrixMeandersNumPy.py +0 -333
- mapFolding/algorithms/matrixMeandersPandas.py +0 -334
- mapfolding-0.16.4.dist-info/RECORD +0 -106
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/WHEEL +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.16.4.dist-info → mapfolding-0.17.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# ruff: noqa: ERA001 T201 T203
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from cytoolz.functoolz import curry as syntacticCurry
|
|
4
|
+
from hunterMakesPy import raiseIfNone
|
|
5
|
+
from itertools import repeat
|
|
6
|
+
from mapFolding.dataBaskets import EliminationState
|
|
7
|
+
from math import prod
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from pprint import pprint
|
|
10
|
+
import gmpy2
|
|
11
|
+
import pandas
|
|
12
|
+
|
|
13
|
+
def ptount(integerAbove3:int, /) -> int:
|
|
14
|
+
"""After subtracting 0b000011 from `zz`, measure the distance from a ***p***ower of ***t***wo's bit c***ount***.
|
|
15
|
+
|
|
16
|
+
Notes
|
|
17
|
+
-----
|
|
18
|
+
- Pronounced "tount" because the "p" is silent.
|
|
19
|
+
- Just like the "p", the reason why this is useful is also silent.
|
|
20
|
+
- I suspect there is a more direct route to measure this but I am unaware of it.
|
|
21
|
+
"""
|
|
22
|
+
return distanceFromPowerOf2(integerAbove3 - 0b000011).bit_count()
|
|
23
|
+
|
|
24
|
+
def bitBiggest(integerAbove0: int, /) -> int:
|
|
25
|
+
"""Find the 0-indexed position of the biggest set bit in `integerAbove0`."""
|
|
26
|
+
return integerAbove0.bit_length() - 1
|
|
27
|
+
|
|
28
|
+
def bitSecond(integerAbove0: int, /) -> int | None:
|
|
29
|
+
"""Find the 0-indexed position of the second biggest set bit, if any, in `integerAbove0`."""
|
|
30
|
+
second = bitBiggest(int(gmpy2.bit_flip(integerAbove0, bitBiggest(integerAbove0))))
|
|
31
|
+
return second if second >= 0 else None
|
|
32
|
+
|
|
33
|
+
def distanceFromPowerOf2(integerAbove0: int, /) -> int:
|
|
34
|
+
return int(gmpy2.f_mod_2exp(integerAbove0, integerAbove0.bit_length() - 1))
|
|
35
|
+
|
|
36
|
+
def multiplicityOfPrimeFactor2(integerAbove0: int, /) -> int:
|
|
37
|
+
"""Compute the number of times `integerAbove0` is divisible by 2; aka 'CTZ', Count Trailing Zeros in the binary form."""
|
|
38
|
+
return raiseIfNone(gmpy2.bit_scan1(integerAbove0))
|
|
39
|
+
|
|
40
|
+
@syntacticCurry
|
|
41
|
+
def numeralOfLengthInBase(mostSignificantDigits: int | list[int], fillerDigits: str = '0', leastSignificantDigits: int | list[int] = 0, positions: int = 8, base: int = 2) -> int:
|
|
42
|
+
"""Prototype."""
|
|
43
|
+
digitsPrefix: tuple[int, ...] = (mostSignificantDigits,) if isinstance(mostSignificantDigits, int) else tuple(mostSignificantDigits)
|
|
44
|
+
quantityPrefix: int = len(digitsPrefix)
|
|
45
|
+
|
|
46
|
+
digitsSuffix: tuple[int, ...] = (leastSignificantDigits,) if isinstance(leastSignificantDigits, int) else tuple(leastSignificantDigits)
|
|
47
|
+
quantitySuffix: int = len(digitsSuffix)
|
|
48
|
+
|
|
49
|
+
quantityFiller: int = positions - quantityPrefix - quantitySuffix
|
|
50
|
+
digitsFiller: tuple[int, ...] = tuple(int(digit) for digit in list(repeat(fillerDigits, quantityFiller))[0:quantityFiller])
|
|
51
|
+
|
|
52
|
+
tupleDigitsMSBtoLSB: tuple[int, ...] = (*digitsPrefix, *digitsFiller, *digitsSuffix)
|
|
53
|
+
digitsAsString: str = ''.join(str(digit) for digit in tupleDigitsMSBtoLSB)
|
|
54
|
+
|
|
55
|
+
numeralAs_int: int = int(digitsAsString, base)
|
|
56
|
+
|
|
57
|
+
return numeralAs_int
|
|
58
|
+
|
|
59
|
+
@syntacticCurry
|
|
60
|
+
def makeFillerDigitsNotation(numeral: int, positions: int = 8, base: int = 2) -> tuple[list[int], str, int | list[int]]:
|
|
61
|
+
"""Represent `numeral` as prefix, filler digit, and suffix for reuse with `numeralOfLengthInBase`.
|
|
62
|
+
|
|
63
|
+
(AI generated docstring)
|
|
64
|
+
|
|
65
|
+
This prototype only supports base 2 and expects a non-negative numeral whose binary expansion
|
|
66
|
+
fits inside the specified number of positions. The returned structure abstracts the repeated
|
|
67
|
+
interior digits so that different position counts share the same notation.
|
|
68
|
+
"""
|
|
69
|
+
if positions <= 0:
|
|
70
|
+
message: str = f'positions must be positive; received {positions}.'
|
|
71
|
+
raise ValueError(message)
|
|
72
|
+
if base != 2:
|
|
73
|
+
message: str = f'makeFillerDigitsNotation currently supports base 2 only; received base {base}.'
|
|
74
|
+
raise ValueError(message)
|
|
75
|
+
if numeral < 0:
|
|
76
|
+
message: str = f'numeral must be non-negative; received {numeral}.'
|
|
77
|
+
raise ValueError(message)
|
|
78
|
+
|
|
79
|
+
digitsAsString: str = f'{numeral:b}'
|
|
80
|
+
if len(digitsAsString) > positions:
|
|
81
|
+
message: str = f'numeral {numeral} requires {len(digitsAsString)} positions; received {positions}.'
|
|
82
|
+
raise ValueError(message)
|
|
83
|
+
digitsAsString = digitsAsString.zfill(positions)
|
|
84
|
+
|
|
85
|
+
lengthPrefix: int | None = None
|
|
86
|
+
lengthSuffix: int | None = None
|
|
87
|
+
lengthFiller: int = -1
|
|
88
|
+
fillerDigit: str = '0'
|
|
89
|
+
|
|
90
|
+
for prefixLength in range(1, positions):
|
|
91
|
+
for suffixLength in range(1, positions - prefixLength + 1):
|
|
92
|
+
fillerLength: int = positions - prefixLength - suffixLength
|
|
93
|
+
if fillerLength < 0:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
if fillerLength == 0:
|
|
97
|
+
candidateFillerDigit: str = digitsAsString[prefixLength - 1]
|
|
98
|
+
else:
|
|
99
|
+
candidateFillerDigit = digitsAsString[prefixLength]
|
|
100
|
+
segmentFiller: str = digitsAsString[prefixLength:prefixLength + fillerLength]
|
|
101
|
+
if segmentFiller != candidateFillerDigit * fillerLength:
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
if ((lengthPrefix is None)
|
|
105
|
+
or (fillerLength > lengthFiller)
|
|
106
|
+
or ((fillerLength == lengthFiller) and (
|
|
107
|
+
(prefixLength < lengthPrefix)
|
|
108
|
+
or ((prefixLength == lengthPrefix) and (suffixLength < lengthSuffix if lengthSuffix is not None else True))))):
|
|
109
|
+
lengthPrefix = prefixLength
|
|
110
|
+
lengthSuffix = suffixLength
|
|
111
|
+
lengthFiller = fillerLength
|
|
112
|
+
fillerDigit = candidateFillerDigit
|
|
113
|
+
|
|
114
|
+
if lengthPrefix is None or lengthSuffix is None:
|
|
115
|
+
lengthPrefix = positions if positions > 0 else 1
|
|
116
|
+
lengthSuffix = max(0, positions - lengthPrefix)
|
|
117
|
+
lengthFiller = 0
|
|
118
|
+
fillerDigit = digitsAsString[lengthPrefix - 1] if positions > 0 else '0'
|
|
119
|
+
|
|
120
|
+
mostSignificantDigits: list[int] = [int(digit) for digit in digitsAsString[0:lengthPrefix]]
|
|
121
|
+
leastSignificantDigitsSequence: list[int] = [int(digit) for digit in digitsAsString[positions - lengthSuffix:]] if lengthSuffix > 0 else []
|
|
122
|
+
leastSignificantDigits: int | list[int]
|
|
123
|
+
if lengthSuffix == 1:
|
|
124
|
+
leastSignificantDigits = leastSignificantDigitsSequence[0]
|
|
125
|
+
else:
|
|
126
|
+
leastSignificantDigits = leastSignificantDigitsSequence
|
|
127
|
+
|
|
128
|
+
notation: tuple[list[int], str, int | list[int]] = (mostSignificantDigits, fillerDigit, leastSignificantDigits)
|
|
129
|
+
return notation
|
|
130
|
+
|
|
131
|
+
def getDictionaryAddends4Next(state: EliminationState) -> dict[int, list[int]]:
|
|
132
|
+
dictionaryAddends: dict[int, list[int]] = {}
|
|
133
|
+
|
|
134
|
+
indexLeaf: int = 0
|
|
135
|
+
listOfDifferences: list[int] = [1]
|
|
136
|
+
dictionaryAddends[indexLeaf] = listOfDifferences
|
|
137
|
+
|
|
138
|
+
productsOfDimensions: list[int] = [prod(state.mapShape[0:dimension], start=1) for dimension in range(state.dimensionsTotal)]
|
|
139
|
+
|
|
140
|
+
for indexLeaf in range(1, state.leavesTotal):
|
|
141
|
+
products下_indexLeaf: list[int] = productsOfDimensions.copy()
|
|
142
|
+
|
|
143
|
+
theMaskOfDirectionality = gmpy2.bit_mask(state.leavesTotal - 1) & indexLeaf
|
|
144
|
+
for index in range(state.dimensionsTotal):
|
|
145
|
+
if gmpy2.bit_test(theMaskOfDirectionality, index):
|
|
146
|
+
products下_indexLeaf[index] *= -1
|
|
147
|
+
|
|
148
|
+
slicingIndexStart: int = (indexLeaf.bit_count() - 1) & 1 ^ 1
|
|
149
|
+
slicingIndexEnd = (indexLeaf.bit_length() - 1) * (slicingIndexStart ^ 1) or None
|
|
150
|
+
|
|
151
|
+
if (slicingIndexStart == 1) and (gmpy2.is_even(indexLeaf)):
|
|
152
|
+
slicingIndexStart += multiplicityOfPrimeFactor2(indexLeaf)
|
|
153
|
+
|
|
154
|
+
products下_indexLeaf = products下_indexLeaf[slicingIndexStart:None]
|
|
155
|
+
products下_indexLeaf = products下_indexLeaf[0:slicingIndexEnd]
|
|
156
|
+
dictionaryAddends[indexLeaf] = products下_indexLeaf
|
|
157
|
+
|
|
158
|
+
return dictionaryAddends
|
|
159
|
+
|
|
160
|
+
def getDictionaryAddends4Prior(state: EliminationState) -> dict[int, list[int]]:
|
|
161
|
+
dictionaryAddends: dict[int, list[int]] = {}
|
|
162
|
+
|
|
163
|
+
indexLeaf: int = 0
|
|
164
|
+
listOfDifferences: list[int] = []
|
|
165
|
+
dictionaryAddends[indexLeaf] = listOfDifferences
|
|
166
|
+
|
|
167
|
+
indexLeaf = 1
|
|
168
|
+
listOfDifferences = [-1]
|
|
169
|
+
dictionaryAddends[indexLeaf] = listOfDifferences
|
|
170
|
+
|
|
171
|
+
productsOfDimensions: list[int] = [prod(state.mapShape[0:dimension], start=1) for dimension in range(state.dimensionsTotal)]
|
|
172
|
+
|
|
173
|
+
for indexLeaf in range(state.leavesTotal - 1, 1, -1):
|
|
174
|
+
products下_indexLeaf: list[int] = productsOfDimensions.copy()
|
|
175
|
+
|
|
176
|
+
theMaskOfDirectionality = gmpy2.bit_mask(state.leavesTotal - 1) & indexLeaf
|
|
177
|
+
for index in range(state.dimensionsTotal):
|
|
178
|
+
if gmpy2.bit_test(theMaskOfDirectionality, index):
|
|
179
|
+
products下_indexLeaf[index] *= -1
|
|
180
|
+
|
|
181
|
+
slicingIndexStart: int = (indexLeaf.bit_count() - 1) & 1
|
|
182
|
+
slicingIndexEnd = (indexLeaf.bit_length() - 1) * (slicingIndexStart ^ 1) or None
|
|
183
|
+
|
|
184
|
+
if (slicingIndexStart == 1) and (gmpy2.is_even(indexLeaf)):
|
|
185
|
+
slicingIndexStart += multiplicityOfPrimeFactor2(indexLeaf)
|
|
186
|
+
|
|
187
|
+
products下_indexLeaf = products下_indexLeaf[slicingIndexStart:None]
|
|
188
|
+
products下_indexLeaf = products下_indexLeaf[0:slicingIndexEnd]
|
|
189
|
+
dictionaryAddends[indexLeaf] = products下_indexLeaf
|
|
190
|
+
|
|
191
|
+
return dictionaryAddends
|
|
192
|
+
|
|
193
|
+
def getIndexLeafRange(state: EliminationState, indexLeaf: int) -> range:
|
|
194
|
+
return range(indexLeaf.bit_count() + (2**(multiplicityOfPrimeFactor2(indexLeaf) + 1) - 2)
|
|
195
|
+
, state.leavesTotal - (2**(state.dimensionsTotal - indexLeaf.bit_length() + 1) - 2) - (indexLeaf.bit_count() - 1)
|
|
196
|
+
, 2)
|
|
197
|
+
|
|
198
|
+
def getDictionaryIndexLeafRanges(state: EliminationState) -> dict[int, range]:
|
|
199
|
+
"""For each `indexLeaf` (not `leaf`), the associated `range` defines
|
|
200
|
+
1. every `pile` at which `indexLeaf` may be found in a `folding` and
|
|
201
|
+
2. in the set of all valid foldings, every `pile` at which `indexLeaf` must be found.
|
|
202
|
+
""" # noqa: D205
|
|
203
|
+
dictionaryIndexLeafRanges: dict[int, range] = {indexLeaf: getIndexLeafRange(state, indexLeaf) for indexLeaf in range(1, state.leavesTotal)}
|
|
204
|
+
|
|
205
|
+
indexLeaf: int = 0
|
|
206
|
+
dictionaryIndexLeafRanges[indexLeaf] = range(0, 1, 2)
|
|
207
|
+
|
|
208
|
+
indexLeaf = state.leavesTotal // 2 + 1
|
|
209
|
+
step = 4
|
|
210
|
+
rangeIndexLeaf: range = dictionaryIndexLeafRanges[indexLeaf]
|
|
211
|
+
dictionaryIndexLeafRanges[indexLeaf] = range(rangeIndexLeaf.start, rangeIndexLeaf.stop, step)
|
|
212
|
+
|
|
213
|
+
return dictionaryIndexLeafRanges
|
|
214
|
+
|
|
215
|
+
# TODO
|
|
216
|
+
def getDictionaryPileToLeavesByFormula(state: EliminationState) -> dict[int, list[int]]:
|
|
217
|
+
dictionaryPileToLeaves: dict[int, list[int]] = {pile: [] for pile in range(state.leavesTotal)}
|
|
218
|
+
|
|
219
|
+
return dictionaryPileToLeaves
|
|
220
|
+
|
|
221
|
+
def getDictionaryPileToLeaves(state: EliminationState) -> dict[int, list[int]]:
|
|
222
|
+
dictionaryPileToLeaves: dict[int, list[int]] = {pile: [] for pile in range(state.leavesTotal)}
|
|
223
|
+
|
|
224
|
+
dictionaryLeafRanges: dict[int, range] = getDictionaryIndexLeafRanges(state)
|
|
225
|
+
|
|
226
|
+
for indexLeaf, rangePilings in dictionaryLeafRanges.items():
|
|
227
|
+
for pile in rangePilings:
|
|
228
|
+
dictionaryPileToLeaves[pile].append(indexLeaf)
|
|
229
|
+
|
|
230
|
+
return dictionaryPileToLeaves
|
|
231
|
+
|
|
232
|
+
def _getGroupedBy(state: EliminationState, pileTarget: int, groupByIndexLeavesAtPiles: tuple[int, ...]) -> dict[int | tuple[int, ...], list[int]]:
|
|
233
|
+
pathFilename = Path(f'/apps/mapFolding/Z0Z_notes/arrayFoldingsP2d{state.dimensionsTotal}.pkl')
|
|
234
|
+
arrayFoldings = pandas.read_pickle(pathFilename) # noqa: S301
|
|
235
|
+
dataframeFoldings = pandas.DataFrame(arrayFoldings)
|
|
236
|
+
|
|
237
|
+
groupedBy: dict[int | tuple[int, ...], list[int]] = dataframeFoldings.groupby(list(groupByIndexLeavesAtPiles))[pileTarget].apply(list).to_dict()
|
|
238
|
+
return {indexLeaves: sorted(set(listLeaves)) for indexLeaves, listLeaves in groupedBy.items()}
|
|
239
|
+
|
|
240
|
+
def getExcludedAddendIndices(state: EliminationState, indexLeafAddend: int, pileTarget: int, groupByIndexLeavesAtPiles: tuple[int, ...]) -> dict[int | tuple[int, ...], list[int]]:
|
|
241
|
+
groupedBy: dict[int | tuple[int, ...], list[int]] = _getGroupedBy(state, pileTarget, groupByIndexLeavesAtPiles)
|
|
242
|
+
|
|
243
|
+
dictionaryExclusion: dict[int | tuple[int, ...], list[int]] = {}
|
|
244
|
+
listAddends: list[int] = getDictionaryAddends4Next(state)[indexLeafAddend]
|
|
245
|
+
|
|
246
|
+
for groupByIndexLeaves, listIndexLeavesIncludedAtPile in groupedBy.items():
|
|
247
|
+
listAddendIndicesIncluded: list[int] = [addendIndex for addendIndex, addend in enumerate(listAddends) if indexLeafAddend + addend in listIndexLeavesIncludedAtPile]
|
|
248
|
+
listAddendIndicesExcluded: list[int] = sorted(set(range(len(listAddends))).difference(set(listAddendIndicesIncluded)))
|
|
249
|
+
dictionaryExclusion[groupByIndexLeaves] = listAddendIndicesExcluded
|
|
250
|
+
|
|
251
|
+
return dictionaryExclusion
|
|
252
|
+
|
|
253
|
+
def getExcludedIndexLeaves(state: EliminationState, pileTarget: int, groupByIndexLeavesAtPiles: tuple[int, ...]) -> dict[int | tuple[int, ...], list[int]]:
|
|
254
|
+
return {indexLeaves: sorted(set(getDictionaryPileToLeaves(state)[pileTarget]).difference(set(listLeaves))) for indexLeaves, listLeaves in _getGroupedBy(state, pileTarget, groupByIndexLeavesAtPiles).items()}
|
|
255
|
+
|
|
256
|
+
if __name__ == '__main__':
|
|
257
|
+
from mapFolding.tests.verify import (
|
|
258
|
+
verifyDictionaryAddends4Next, verifyDictionaryAddends4Prior, verifyDictionaryLeafRanges)
|
|
259
|
+
|
|
260
|
+
state = EliminationState((2,) * 6)
|
|
261
|
+
dictionaryLeafRanges = getDictionaryIndexLeafRanges(state)
|
|
262
|
+
# verifyDictionaryLeafRanges(state, dictionaryLeafRanges)
|
|
263
|
+
dictionaryAddends4Next = getDictionaryAddends4Next(state)
|
|
264
|
+
# verifyDictionaryAddends4Next(state, dictionaryAddends4Next)
|
|
265
|
+
dictionaryAddends4Prior = getDictionaryAddends4Prior(state)
|
|
266
|
+
verifyDictionaryAddends4Prior(state, dictionaryAddends4Prior)
|
|
267
|
+
|
|
268
|
+
# dictionaryPileToLeaves = getDictionaryPileToLeaves(state)
|
|
269
|
+
colorReset = '\33[0m'
|
|
270
|
+
color = '\33[91m'
|
|
271
|
+
|
|
272
|
+
# print(dictionaryPileToLeaves[31])
|
|
273
|
+
|
|
274
|
+
# for indexLeaf in [*dictionaryPileToLeaves[31]]:
|
|
275
|
+
# print(f"{indexLeaf:2}: {distanceFromPowerOf2(indexLeaf - 0b000011).bit_count()} ", end='')
|
|
276
|
+
# for d in range(state.dimensionsTotal - 1, -1, -1):
|
|
277
|
+
# bit = gmpy2.bit_test(indexLeaf, d)
|
|
278
|
+
# print(f'\33[{3+(d&0)}{int(bit+3)}m', "█▊", colorReset, sep='', end='')
|
|
279
|
+
# print()
|
|
280
|
+
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# ruff: noqa ERA001
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from gmpy2 import bit_test, is_even, is_odd
|
|
4
|
+
from hunterMakesPy import raiseIfNone
|
|
5
|
+
from mapFolding.algorithms.patternFinder import (
|
|
6
|
+
bitBiggest, bitSecond, distanceFromPowerOf2, getDictionaryAddends4Next, getDictionaryAddends4Prior,
|
|
7
|
+
getDictionaryLeafRanges, getDictionaryPileToLeaves, getExcludedAddendIndices, getExcludedIndexLeaves,
|
|
8
|
+
multiplicityOfPrimeFactor2, numeralOfLengthInBase)
|
|
9
|
+
from mapFolding.algorithms.pinning2DnAnnex import addItUp, exclude_rBefore_k
|
|
10
|
+
from mapFolding.dataBaskets import EliminationState
|
|
11
|
+
from mapFolding.tests.verify import printStatisticsPermutations, verifyPinning2Dn
|
|
12
|
+
from math import log2, prod
|
|
13
|
+
from pprint import pprint
|
|
14
|
+
|
|
15
|
+
def pinByFormula(state: EliminationState, maximumListPinnedLeaves: int = 5000) -> EliminationState:
|
|
16
|
+
if not ((state.dimensionsTotal > 2) and (state.mapShape[0] == 2)):
|
|
17
|
+
return state
|
|
18
|
+
|
|
19
|
+
def appendPinnedLeavesAtPile(pinnedLeavesWorkbench: dict[int, int], listIndexLeavesAtPile: list[int], pile: int, mapShape: tuple[int, ...]) -> None:
|
|
20
|
+
for indexLeaf in listIndexLeavesAtPile:
|
|
21
|
+
if indexLeaf < sumsProductsOfDimensions[0]:
|
|
22
|
+
continue
|
|
23
|
+
|
|
24
|
+
if indexLeaf > sumsProductsOfDimensions[-1]:
|
|
25
|
+
continue
|
|
26
|
+
|
|
27
|
+
if indexLeaf in pinnedLeavesWorkbench.values():
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
if pile not in list(dictionaryLeafRanges[indexLeaf]):
|
|
31
|
+
continue
|
|
32
|
+
|
|
33
|
+
if exclude_rBefore_k(pile, indexLeaf, pinnedLeavesWorkbench, mapShape):
|
|
34
|
+
continue
|
|
35
|
+
|
|
36
|
+
pileToPin: int = pile
|
|
37
|
+
pinnedLeaves: dict[int, int] = pinnedLeavesWorkbench.copy()
|
|
38
|
+
|
|
39
|
+
if indexLeaf in [0b000011, ordinal([0,1],'0',0)]:
|
|
40
|
+
pinnedLeaves[pileToPin] = indexLeaf
|
|
41
|
+
pileToPin += 1
|
|
42
|
+
indexLeaf += dictionaryAddends4Next[indexLeaf][0]
|
|
43
|
+
|
|
44
|
+
if indexLeaf in [0b000010, ordinal([1,1],'0',0)]:
|
|
45
|
+
pinnedLeaves[pileToPin] = indexLeaf
|
|
46
|
+
pileToPin -= 1
|
|
47
|
+
indexLeaf += dictionaryAddends4Prior[indexLeaf][0]
|
|
48
|
+
|
|
49
|
+
pinnedLeaves[pileToPin] = indexLeaf
|
|
50
|
+
state.listPinnedLeaves.append(pinnedLeaves.copy())
|
|
51
|
+
|
|
52
|
+
def nextPinnedLeavesWorkbench(state: EliminationState) -> dict[int, int] | None:
|
|
53
|
+
pinnedLeavesWorkbench: dict[int, int] | None = None
|
|
54
|
+
for pile in pileProcessingOrder:
|
|
55
|
+
if pile == queueStopBefore:
|
|
56
|
+
break
|
|
57
|
+
if not all(pile in pinnedLeaves for pinnedLeaves in state.listPinnedLeaves):
|
|
58
|
+
pinnedLeavesWorkbench = next((pinnedLeaves.copy() for pinnedLeaves in state.listPinnedLeaves if pile not in pinnedLeaves))
|
|
59
|
+
state.listPinnedLeaves.remove(pinnedLeavesWorkbench)
|
|
60
|
+
break
|
|
61
|
+
return pinnedLeavesWorkbench
|
|
62
|
+
|
|
63
|
+
def whereNext(pilingsPinned: list[int]) -> int:
|
|
64
|
+
return next(pile for pile in pileProcessingOrder if pile not in pilingsPinned)
|
|
65
|
+
|
|
66
|
+
ordinal: Callable[[int | list[int], str, int | list[int]], int] = numeralOfLengthInBase(positions=state.dimensionsTotal, base=state.mapShape[0])
|
|
67
|
+
"""Prototype."""
|
|
68
|
+
|
|
69
|
+
productsOfDimensions: list[int] = [prod(state.mapShape[0:dimension]) for dimension in range(state.dimensionsTotal + 1)]
|
|
70
|
+
sumsProductsOfDimensions: list[int] = [sum(productsOfDimensions[0:dimension]) for dimension in range(state.dimensionsTotal + 1)]
|
|
71
|
+
|
|
72
|
+
dictionaryAddends4Next: dict[int, list[int]] = getDictionaryAddends4Next(state)
|
|
73
|
+
dictionaryAddends4Prior: dict[int, list[int]] = getDictionaryAddends4Prior(state)
|
|
74
|
+
dictionaryLeafRanges: dict[int, range] = getDictionaryLeafRanges(state)
|
|
75
|
+
dictionaryPileToLeaves: dict[int, list[int]] = getDictionaryPileToLeaves(state)
|
|
76
|
+
|
|
77
|
+
state.listPinnedLeaves = state.listPinnedLeaves or [{0b000000: 0b000000}]
|
|
78
|
+
|
|
79
|
+
pileProcessingOrder: list[int] = [0b000000, 0b000001, 0b000010, ordinal([1,1],'1',1), ordinal([1,1],'1',0), 0b000011, ordinal([1,1],'1',[0,1]), 0b000100]
|
|
80
|
+
# pileProcessingOrder.extend([5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
|
|
81
|
+
|
|
82
|
+
pileProcessingOrder.extend([ordinal([0,1],'1',1), ordinal([0,1],'0',1), ordinal([1,1],'0',1)])
|
|
83
|
+
queueStopBefore: int = ordinal([0,1],'0',1)
|
|
84
|
+
|
|
85
|
+
oneTime: int = 0
|
|
86
|
+
|
|
87
|
+
while (len(state.listPinnedLeaves) < maximumListPinnedLeaves) and (pinnedLeavesWorkbench := nextPinnedLeavesWorkbench(state)):
|
|
88
|
+
pile: int = whereNext(list(pinnedLeavesWorkbench.keys()))
|
|
89
|
+
listIndexLeavesAtPile: list[int] = []
|
|
90
|
+
listAddendIndicesExcluded: list[int] = []
|
|
91
|
+
listRemoveIndexLeaves: list[int] = []
|
|
92
|
+
|
|
93
|
+
if pile == 0b000000:
|
|
94
|
+
listIndexLeavesAtPile.append(0b000000)
|
|
95
|
+
if pile == 0b000001:
|
|
96
|
+
listIndexLeavesAtPile.append(0b000001)
|
|
97
|
+
if pile == 0b000010:
|
|
98
|
+
listIndexLeavesAtPile = addItUp(dictionaryAddends4Next, pinnedLeavesWorkbench[pile - 1], listAddendIndicesExcluded)
|
|
99
|
+
if pile == ordinal([1,1],'1',1):
|
|
100
|
+
listIndexLeavesAtPile.append(ordinal([1,0],'0',0))
|
|
101
|
+
if pile == ordinal([1,1],'1',0):
|
|
102
|
+
indexLeafAt__10: int = pinnedLeavesWorkbench[0b000010]
|
|
103
|
+
if indexLeafAt__10.bit_length() < state.dimensionsTotal:
|
|
104
|
+
listAddendIndicesExcluded.extend([*range(0b000001, indexLeafAt__10.bit_length())])
|
|
105
|
+
listIndexLeavesAtPile = addItUp(dictionaryAddends4Prior, pinnedLeavesWorkbench[pile + 1], listAddendIndicesExcluded)
|
|
106
|
+
if pile == 0b000011:
|
|
107
|
+
listAddendIndicesExcluded.append(0)
|
|
108
|
+
indexLeafAtPileLess1: int = pinnedLeavesWorkbench[pile - 1]
|
|
109
|
+
indexLeafAt11ones0: int = pinnedLeavesWorkbench[ordinal([1,1],'1',0)]
|
|
110
|
+
if is_even(indexLeafAt11ones0) and (indexLeafAtPileLess1 == ordinal([1,0],'0',1)):
|
|
111
|
+
listAddendIndicesExcluded.extend([*range(multiplicityOfPrimeFactor2(pinnedLeavesWorkbench[ordinal([1,1],'1',0)]) + 1, state.dimensionsTotal)])
|
|
112
|
+
listIndexLeavesAtPile = addItUp(dictionaryAddends4Next, indexLeafAtPileLess1, listAddendIndicesExcluded)
|
|
113
|
+
if pile == ordinal([1,1],'1',[0,1]):
|
|
114
|
+
indexLeafAtPilePlus1: int = pinnedLeavesWorkbench[pile + 1]
|
|
115
|
+
if indexLeafAtPilePlus1 < ordinal([1,1],'0',0):
|
|
116
|
+
listAddendIndicesExcluded.append(-1)
|
|
117
|
+
indexLeafAt__10 = pinnedLeavesWorkbench[0b000010]
|
|
118
|
+
if (indexLeafAtPilePlus1 == ordinal([1,0],'0',1)) and (indexLeafAt__10 != 0b000011):
|
|
119
|
+
listAddendIndicesExcluded.extend([*range(0, indexLeafAt__10.bit_length() - 2)])
|
|
120
|
+
listIndexLeavesAtPile = addItUp(dictionaryAddends4Prior, indexLeafAtPilePlus1, listAddendIndicesExcluded)
|
|
121
|
+
if pile == 0b000100:
|
|
122
|
+
indexLeafAtPileLess1 = pinnedLeavesWorkbench[pile - 1]
|
|
123
|
+
if is_odd(indexLeafAtPileLess1):
|
|
124
|
+
listAddendIndicesExcluded.extend([*range(indexLeafAtPileLess1.bit_length() - 1, 5), distanceFromPowerOf2(indexLeafAtPileLess1 - 0b000011).bit_count()])
|
|
125
|
+
indexLeafAt11ones0 = pinnedLeavesWorkbench[ordinal([1,1],'1',0)]
|
|
126
|
+
if is_even(indexLeafAtPileLess1) and is_even(indexLeafAt11ones0):
|
|
127
|
+
listAddendIndicesExcluded.extend([*range(multiplicityOfPrimeFactor2(distanceFromPowerOf2(indexLeafAt11ones0)) - 0b000010, (state.dimensionsTotal - 3))])
|
|
128
|
+
if is_odd(indexLeafAtPileLess1):
|
|
129
|
+
listAddendIndicesExcluded.append((int(log2(distanceFromPowerOf2(indexLeafAt11ones0))) + 4) % 5)
|
|
130
|
+
indexLeafAt11ones01: int = pinnedLeavesWorkbench[ordinal([1,1],'1',[0,1])]
|
|
131
|
+
if is_even(indexLeafAtPileLess1) and indexLeafAt11ones01:
|
|
132
|
+
listAddendIndicesExcluded.extend([*range((state.dimensionsTotal - 3))][(state.dimensionsTotal - 3) - ((state.dimensionsTotal - 2) - distanceFromPowerOf2(indexLeafAt11ones01 - (indexLeafAt11ones01.bit_count() - is_even(indexLeafAt11ones01))).bit_count()) % (state.dimensionsTotal - 2) - is_even(indexLeafAt11ones01): None])
|
|
133
|
+
indexLeafAt__10 = pinnedLeavesWorkbench[0b000010]
|
|
134
|
+
if (indexLeafAt__10 == ordinal([1,0],'0',1)):
|
|
135
|
+
listAddendIndicesExcluded.extend([(int(log2(distanceFromPowerOf2(indexLeafAt11ones0))) + 4) % 5, multiplicityOfPrimeFactor2(indexLeafAt11ones01) - 1])
|
|
136
|
+
if (indexLeafAt__10 == ordinal([1,0],'0',1)) and (indexLeafAt11ones01 > ordinal([1,0],'0',1)):
|
|
137
|
+
listAddendIndicesExcluded.extend([*range(int(indexLeafAt11ones01 - 2**(indexLeafAt11ones01.bit_length() - 1)).bit_length() - 1, state.dimensionsTotal - 2)])
|
|
138
|
+
if ((indexLeafAt__10 == ordinal([1,0],'0',1)) and (0 < indexLeafAtPileLess1 - indexLeafAt__10 <= 2**(state.dimensionsTotal - 4)) and (0 < (indexLeafAt11ones0 - indexLeafAtPileLess1) <= 2**(state.dimensionsTotal - 3))):
|
|
139
|
+
listAddendIndicesExcluded.extend([distanceFromPowerOf2(indexLeafAtPileLess1 - 0b11).bit_count(), state.dimensionsTotal - 3, state.dimensionsTotal - 4])
|
|
140
|
+
listIndexLeavesAtPile = addItUp(dictionaryAddends4Next, indexLeafAtPileLess1, listAddendIndicesExcluded)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if pile == ordinal([0,1],'1',1):
|
|
144
|
+
listRemoveIndexLeaves = []
|
|
145
|
+
|
|
146
|
+
pileExcluder: int = 0b000010
|
|
147
|
+
indexLeafAtPileExcluder: int = pinnedLeavesWorkbench[pileExcluder]
|
|
148
|
+
for d in range(state.dimensionsTotal):
|
|
149
|
+
if d < state.dimensionsTotal - 2:
|
|
150
|
+
indexLeaf: int = dictionaryPileToLeaves[pileExcluder][d]
|
|
151
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
152
|
+
listRemoveIndexLeaves.extend([0b000010, ordinal([1,0],'0',0) + indexLeafAtPileExcluder])
|
|
153
|
+
if 0 < d < state.dimensionsTotal - 2:
|
|
154
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
155
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
156
|
+
listRemoveIndexLeaves.extend([0b000010 + indexLeafAtPileExcluder])
|
|
157
|
+
if d == 1:
|
|
158
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
159
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
160
|
+
listRemoveIndexLeaves.extend([ordinal([1,0],'0',0) + indexLeafAtPileExcluder + 1])
|
|
161
|
+
if d == state.dimensionsTotal - 2:
|
|
162
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
163
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
164
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0), ordinal([0,1],'0',0) + indexLeafAtPileExcluder])
|
|
165
|
+
del pileExcluder
|
|
166
|
+
|
|
167
|
+
pileExcluder = ordinal([1,1],'1',0)
|
|
168
|
+
indexLeafAtPileExcluder = pinnedLeavesWorkbench[pileExcluder]
|
|
169
|
+
for d in range(state.dimensionsTotal):
|
|
170
|
+
if d == 0:
|
|
171
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
172
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
173
|
+
listRemoveIndexLeaves.extend([0b000010])
|
|
174
|
+
if d < state.dimensionsTotal - 2:
|
|
175
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
176
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
177
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0) + indexLeafAtPileExcluder])
|
|
178
|
+
if 0 < d < state.dimensionsTotal - 2:
|
|
179
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
180
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
181
|
+
listRemoveIndexLeaves.extend([2**d, ordinal([0,1],'0',0) + indexLeafAtPileExcluder - (2**d - 0b000001)])
|
|
182
|
+
if 0 < d < state.dimensionsTotal - 3:
|
|
183
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
184
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
185
|
+
listRemoveIndexLeaves.extend([0b000001 + indexLeafAtPileExcluder])
|
|
186
|
+
if 0 < d < state.dimensionsTotal - 1:
|
|
187
|
+
indexLeaf = dictionaryPileToLeaves[pileExcluder][d]
|
|
188
|
+
if indexLeaf == indexLeafAtPileExcluder:
|
|
189
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0)])
|
|
190
|
+
del pileExcluder
|
|
191
|
+
|
|
192
|
+
"""indexLeafAt__11
|
|
193
|
+
(2,) * 5:
|
|
194
|
+
13 False [2, 4, 7, 11, 13, 19, 21, 25, 28] [13, 4, 2, 28, 25, 11, 19]
|
|
195
|
+
25 False [8, 25, 28] [25, 8, 25, 8]
|
|
196
|
+
|
|
197
|
+
(2,) * 6:
|
|
198
|
+
13 False [2, 4, 7, 11, 13, 35, 37, 41, 44] [13, 4, 2, 44, 41, 11, 35]
|
|
199
|
+
21 False [2, 4, 8, 19, 21, 25, 28, 35, 49, 52, 56] [21, 4, 2, 52, 49, 19, 35]
|
|
200
|
+
25 False [2, 8, 19, 25, 41, 49, 56, 59] [25, 8, 2, 56, 49]
|
|
201
|
+
49 False [16, 49, 56] [49, 16, 49, 16]
|
|
202
|
+
"""
|
|
203
|
+
pileExcluder = 0b000011
|
|
204
|
+
indexLeafAtPileExcluder = pinnedLeavesWorkbench[pileExcluder]
|
|
205
|
+
|
|
206
|
+
if is_odd(indexLeafAtPileExcluder):
|
|
207
|
+
listRemoveIndexLeaves.extend([indexLeafAtPileExcluder, productsOfDimensions[raiseIfNone(bitSecond(indexLeafAtPileExcluder))]])
|
|
208
|
+
|
|
209
|
+
if indexLeafAtPileExcluder < ordinal([1,0],'0',0):
|
|
210
|
+
comebackOffset: int = sumsProductsOfDimensions[distanceFromPowerOf2(indexLeafAtPileExcluder - 0b000011).bit_count() + 1]
|
|
211
|
+
listRemoveIndexLeaves.extend([
|
|
212
|
+
0b000010
|
|
213
|
+
, indexLeafAtPileExcluder + ordinal([0,1],'1',1)
|
|
214
|
+
, indexLeafAtPileExcluder + ordinal([0,1],'1',1) - comebackOffset
|
|
215
|
+
])
|
|
216
|
+
if distanceFromPowerOf2(indexLeafAtPileExcluder - 0b000011).bit_count() == 1:
|
|
217
|
+
listRemoveIndexLeaves.extend([
|
|
218
|
+
productsOfDimensions[bitBiggest(indexLeafAtPileExcluder)] + comebackOffset
|
|
219
|
+
, ordinal([1,0],'0',0) + comebackOffset
|
|
220
|
+
])
|
|
221
|
+
|
|
222
|
+
if ordinal([1,0],'0',0) < indexLeafAtPileExcluder:
|
|
223
|
+
listRemoveIndexLeaves.extend([ordinal([1,1],'0',1), productsOfDimensions[bitBiggest(indexLeafAtPileExcluder) - 1]])
|
|
224
|
+
del pileExcluder
|
|
225
|
+
|
|
226
|
+
"""ordinal([1,1],'1',[0,1])
|
|
227
|
+
38: [2, 4, 16, 21, 35, 37, 38, 49, 50], # NOTE missing 21
|
|
228
|
+
42: [2, 4, 14, 16, 35, 37, 38, 41, 42, 49, 50], # NOTE missing 4, 14, 37, 38, 41
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
pileExcluder = ordinal([1,1],'1',[0,1])
|
|
232
|
+
indexLeafAtPileExcluder = pinnedLeavesWorkbench[pileExcluder]
|
|
233
|
+
if ordinal([1,0],'0',0) < indexLeafAtPileExcluder:
|
|
234
|
+
listRemoveIndexLeaves.extend([ordinal([1,1],'0',1), indexLeafAtPileExcluder])
|
|
235
|
+
|
|
236
|
+
if is_even(indexLeafAtPileExcluder):
|
|
237
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0)])
|
|
238
|
+
bit = 1
|
|
239
|
+
if bit_test(indexLeafAtPileExcluder, bit):
|
|
240
|
+
listRemoveIndexLeaves.extend([2**bit, ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
241
|
+
listRemoveIndexLeaves.extend([state.leavesTotal - sum(productsOfDimensions[bit: state.dimensionsTotal - 2])])
|
|
242
|
+
bit = 2
|
|
243
|
+
if bit_test(indexLeafAtPileExcluder, bit):
|
|
244
|
+
listRemoveIndexLeaves.extend([2**bit, ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
245
|
+
if 1 < multiplicityOfPrimeFactor2(indexLeafAtPileExcluder):
|
|
246
|
+
listRemoveIndexLeaves.extend([state.leavesTotal - sum(productsOfDimensions[bit: state.dimensionsTotal - 2])])
|
|
247
|
+
bit = 3
|
|
248
|
+
if bit_test(indexLeafAtPileExcluder, bit) and (1 < multiplicityOfPrimeFactor2(indexLeafAtPileExcluder)):
|
|
249
|
+
listRemoveIndexLeaves.extend([2**bit])
|
|
250
|
+
listRemoveIndexLeaves.extend([state.leavesTotal - sum(productsOfDimensions[bit: state.dimensionsTotal - 2])])
|
|
251
|
+
if multiplicityOfPrimeFactor2(indexLeafAtPileExcluder) < state.dimensionsTotal - 3:
|
|
252
|
+
listRemoveIndexLeaves.extend([ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
253
|
+
|
|
254
|
+
if is_odd(indexLeafAtPileExcluder):
|
|
255
|
+
listRemoveIndexLeaves.extend([0b000010])
|
|
256
|
+
|
|
257
|
+
sheepOrGoat = distanceFromPowerOf2(indexLeafAtPileExcluder - 0b000011).bit_count()
|
|
258
|
+
if 0 < sheepOrGoat < state.dimensionsTotal - 3:
|
|
259
|
+
comebackOffset = 2**bitBiggest(indexLeafAtPileExcluder) - 2
|
|
260
|
+
listRemoveIndexLeaves.extend([indexLeafAtPileExcluder - comebackOffset])
|
|
261
|
+
if 0 < sheepOrGoat < state.dimensionsTotal - 4:
|
|
262
|
+
comebackOffset = 2**raiseIfNone(bitSecond(indexLeafAtPileExcluder)) - 2
|
|
263
|
+
listRemoveIndexLeaves.extend([indexLeafAtPileExcluder - comebackOffset])
|
|
264
|
+
|
|
265
|
+
pileExcluder = 0b000100
|
|
266
|
+
indexLeafAtPileExcluder = pinnedLeavesWorkbench[pileExcluder]
|
|
267
|
+
|
|
268
|
+
if is_even(indexLeafAtPileExcluder):
|
|
269
|
+
listRemoveIndexLeaves.extend([0b000010, indexLeafAtPileExcluder + 1, ordinal([1,0],'0',0) + 0b000011])
|
|
270
|
+
if is_odd(indexLeafAtPileExcluder):
|
|
271
|
+
listRemoveIndexLeaves.extend([indexLeafAtPileExcluder - 1])
|
|
272
|
+
if ordinal([0,1],'0',0) < indexLeafAtPileExcluder < ordinal([1,0],'0',0):
|
|
273
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0) + 0b000011, ordinal([1,1],'0',1)])
|
|
274
|
+
if ordinal([1,0],'0',0) < indexLeafAtPileExcluder:
|
|
275
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0), ordinal([1,1],'0',1)])
|
|
276
|
+
bit = 1
|
|
277
|
+
if bit_test(indexLeafAtPileExcluder, bit):
|
|
278
|
+
listRemoveIndexLeaves.extend([2**bit, ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
279
|
+
bit = 2
|
|
280
|
+
if bit_test(indexLeafAtPileExcluder, bit):
|
|
281
|
+
listRemoveIndexLeaves.extend([ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
282
|
+
bit = 3
|
|
283
|
+
if bit_test(indexLeafAtPileExcluder, bit):
|
|
284
|
+
listRemoveIndexLeaves.extend([ordinal([1,0],'0',0) + 2**bit + 0b000001])
|
|
285
|
+
bit = 4
|
|
286
|
+
if bit_test(indexLeafAtPileExcluder, bit) and (indexLeafAtPileExcluder.bit_length() > 5):
|
|
287
|
+
listRemoveIndexLeaves.extend([ordinal([1,1,1],'0',0)])
|
|
288
|
+
del pileExcluder
|
|
289
|
+
|
|
290
|
+
indexLeafAt__10 = pinnedLeavesWorkbench[0b000010]
|
|
291
|
+
indexLeafAt11ones0 = pinnedLeavesWorkbench[ordinal([1,1],'1',0)]
|
|
292
|
+
indexLeafAt__11 = pinnedLeavesWorkbench[0b000011]
|
|
293
|
+
indexLeafAt11ones01 = pinnedLeavesWorkbench[ordinal([1,1],'1',[0,1])]
|
|
294
|
+
|
|
295
|
+
if (indexLeafAt__11 != ordinal([1,1],'0',1)) and (indexLeafAt11ones0 == ordinal([1,1],'0',0)):
|
|
296
|
+
listRemoveIndexLeaves.append(0b000010)
|
|
297
|
+
if (indexLeafAt11ones01 != ordinal([1,0],'0',1) + dictionaryAddends4Prior[ordinal([1,0],'0',1)][0]) and (indexLeafAt__10 == 0b000011):
|
|
298
|
+
listRemoveIndexLeaves.append(ordinal([0,1],'0',0))
|
|
299
|
+
|
|
300
|
+
tuplePilesExcluders = (0b000010, ordinal([1,1],'1',0))
|
|
301
|
+
(indexLeavesAtPilesExcluders) = (indexLeafAt__10, indexLeafAt11ones0)
|
|
302
|
+
if (indexLeafAt__10 == ordinal([0,0,1],'0',1)) and (indexLeafAt11ones0 == ordinal([1,1],'0',0)):
|
|
303
|
+
listRemoveIndexLeaves.extend([ordinal([0,0,1],'0',0), ordinal([1,1,1],'0',0)])
|
|
304
|
+
if indexLeafAt__10 == ordinal([1,0],'0',1):
|
|
305
|
+
listRemoveIndexLeaves.extend([ordinal([0,1],'0',0), indexLeafAt11ones0 + 0b000001])
|
|
306
|
+
if indexLeafAt__10.bit_length() < state.dimensionsTotal - 2:
|
|
307
|
+
listRemoveIndexLeaves.extend([0b000010, indexLeafAt11ones0 + 0b000010])
|
|
308
|
+
|
|
309
|
+
tuplePilesExcluders = (0b000010, 0b000011)
|
|
310
|
+
(indexLeavesAtPilesExcluders) = (indexLeafAt__10, indexLeafAt__11)
|
|
311
|
+
|
|
312
|
+
tuplePilesExcluders = (ordinal([1,1],'1',0), ordinal([1,1],'1',[0,1]))
|
|
313
|
+
(indexLeavesAtPilesExcluders) = (indexLeafAt11ones0, indexLeafAt11ones01)
|
|
314
|
+
|
|
315
|
+
tuplePilesExcluders = (0b000011, ordinal([1,1],'1',[0,1]))
|
|
316
|
+
(indexLeavesAtPilesExcluders) = (indexLeafAt__11, indexLeafAt11ones01)
|
|
317
|
+
|
|
318
|
+
# listRemoveIndexLeaves: list[int] = []
|
|
319
|
+
|
|
320
|
+
dictionaryExcludedIndexLeaves = getExcludedIndexLeaves(state, pile, tuplePilesExcluders)
|
|
321
|
+
if oneTime < 1:
|
|
322
|
+
oneTime += 1
|
|
323
|
+
# pprint(dictionaryExcludedIndexLeaves, width=140)
|
|
324
|
+
|
|
325
|
+
listExcludedIndexLeavesGoal = dictionaryExcludedIndexLeaves[((indexLeavesAtPilesExcluders))]
|
|
326
|
+
|
|
327
|
+
# print(indexLeavesAtPilesExcluders, sorted(set(listExcludedIndexLeavesGoal).difference(set(listRemoveIndexLeaves)))
|
|
328
|
+
# , listExcludedIndexLeavesGoal == sorted(set(listRemoveIndexLeaves)), sorted(set(listRemoveIndexLeaves)), listExcludedIndexLeavesGoal, sep='\t')
|
|
329
|
+
|
|
330
|
+
listIndexLeavesAtPile = sorted(set(dictionaryPileToLeaves[pile]).difference(set(listRemoveIndexLeaves)))
|
|
331
|
+
|
|
332
|
+
appendPinnedLeavesAtPile(pinnedLeavesWorkbench, listIndexLeavesAtPile, pile, state.mapShape)
|
|
333
|
+
|
|
334
|
+
return state
|
|
335
|
+
|
|
336
|
+
if __name__ == '__main__':
|
|
337
|
+
state = EliminationState((2,) * 5)
|
|
338
|
+
state: EliminationState = pinByFormula(state)
|
|
339
|
+
|
|
340
|
+
# pprint(state.listPinnedLeaves)
|
|
341
|
+
print(f"{len(state.listPinnedLeaves)=}")
|
|
342
|
+
|
|
343
|
+
printStatisticsPermutations(state)
|
|
344
|
+
verifyPinning2Dn(state)
|
|
345
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from itertools import pairwise, repeat
|
|
2
|
+
from mapFolding import exclude
|
|
3
|
+
from mapFolding.algorithms.patternFinder import getDictionaryLeafRanges
|
|
4
|
+
from mapFolding.dataBaskets import EliminationState
|
|
5
|
+
from math import prod
|
|
6
|
+
from operator import add
|
|
7
|
+
|
|
8
|
+
def secondOrderLeaves(state: EliminationState) -> EliminationState:
|
|
9
|
+
if not ((state.dimensionsTotal > 2) and (state.mapShape[0] == 2)):
|
|
10
|
+
return state
|
|
11
|
+
|
|
12
|
+
for pile in getDictionaryLeafRanges(state)[state.leavesTotal//2**2]:
|
|
13
|
+
state.listPinnedLeaves.append({0: 0, 1: 1
|
|
14
|
+
, pile : (1) * state.leavesTotal//2**2
|
|
15
|
+
, pile + 1 : (2**2 - 1) * state.leavesTotal//2**2
|
|
16
|
+
, state.leavesTotal - 1 : state.leavesTotal//2**1})
|
|
17
|
+
|
|
18
|
+
return state
|
|
19
|
+
|
|
20
|
+
def secondOrderPilings(state: EliminationState) -> EliminationState:
|
|
21
|
+
if not ((state.dimensionsTotal > 2) and (state.mapShape[0] == 2)):
|
|
22
|
+
return state
|
|
23
|
+
|
|
24
|
+
dictionaryLeafRanges: dict[int, range] = getDictionaryLeafRanges(state)
|
|
25
|
+
pile: int = state.leavesTotal//2**1
|
|
26
|
+
for indexLeaf in range(state.leavesTotal):
|
|
27
|
+
if pile in list(dictionaryLeafRanges[indexLeaf]):
|
|
28
|
+
state.listPinnedLeaves.append({0: 0, 1: 1
|
|
29
|
+
, pile : indexLeaf
|
|
30
|
+
, state.leavesTotal - 1 : state.leavesTotal//2**1})
|
|
31
|
+
|
|
32
|
+
return state
|
|
33
|
+
|
|
34
|
+
def addItUp(dictionaryAddends: dict[int, list[int]], indexLeafAddend: int, listIndicesExcluded: list[int]) -> list[int]:
|
|
35
|
+
return list(map(add, repeat(indexLeafAddend), exclude(dictionaryAddends[indexLeafAddend], listIndicesExcluded)))
|
|
36
|
+
|
|
37
|
+
def exclude_rBefore_k(pile: int, indexLeaf: int, pinnedLeaves: dict[int, int], mapShape: tuple[int, ...]) -> bool:
|
|
38
|
+
productsOfDimensions: list[int] = [prod(mapShape[0:dimension]) for dimension in range((len(mapShape)) + 1)]
|
|
39
|
+
dictionary_r_to_k: dict[int, int] = {r: k for k, r in pairwise(productsOfDimensions[0:-1])}
|
|
40
|
+
|
|
41
|
+
if (k := dictionary_r_to_k.get(indexLeaf)) and (pileOf_k := next(iter(pilePinned for pilePinned, indexLeafPinned in pinnedLeaves.items() if indexLeafPinned == k), None)):
|
|
42
|
+
return pile < pileOf_k
|
|
43
|
+
return False
|