mapFolding 0.13.1__py3-none-any.whl → 0.14.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.
Files changed (38) hide show
  1. mapFolding/_oeisFormulas/A000136.py +4 -0
  2. mapFolding/_oeisFormulas/A000560.py +4 -0
  3. mapFolding/_oeisFormulas/A000682.py +17 -0
  4. mapFolding/_oeisFormulas/A005315.py +4 -0
  5. mapFolding/_oeisFormulas/A005316.py +10 -0
  6. mapFolding/_oeisFormulas/A223094.py +7 -0
  7. mapFolding/_oeisFormulas/A259702.py +4 -0
  8. mapFolding/_oeisFormulas/A301620.py +6 -0
  9. mapFolding/_oeisFormulas/Z0Z_aOFn.py +19 -0
  10. mapFolding/_oeisFormulas/Z0Z_oeisMeanders.py +53 -0
  11. mapFolding/_oeisFormulas/__init__.py +1 -0
  12. mapFolding/_oeisFormulas/matrixMeanders.py +65 -0
  13. mapFolding/_oeisFormulas/matrixMeandersAnnex.py +84 -0
  14. mapFolding/_theSSOT.py +68 -26
  15. mapFolding/basecamp.py +2 -2
  16. mapFolding/beDRY.py +1 -1
  17. mapFolding/oeis.py +56 -167
  18. mapFolding/reference/A005316JavaPort.py +134 -0
  19. mapFolding/reference/A005316imperative.py +101 -0
  20. mapFolding/reference/A005316intOptimized.py +122 -0
  21. mapFolding/reference/A005316optimized128bit.py +79 -0
  22. mapFolding/reference/A005316primitiveOptimized.py +97 -0
  23. mapFolding/reference/A005316redis.py +118 -0
  24. mapFolding/reference/A005316write2disk.py +169 -0
  25. mapFolding/reference/irvineJavaPort.py +4 -8
  26. mapFolding/reference/matrixMeandersBaseline.py +65 -0
  27. mapFolding/reference/matrixMeandersBaselineAnnex.py +84 -0
  28. mapFolding/someAssemblyRequired/makeJobTheorem2codon.py +45 -17
  29. mapFolding/tests/conftest.py +13 -13
  30. mapFolding/tests/test_computations.py +4 -4
  31. mapFolding/tests/test_oeis.py +7 -14
  32. mapfolding-0.14.0.dist-info/METADATA +78 -0
  33. {mapfolding-0.13.1.dist-info → mapfolding-0.14.0.dist-info}/RECORD +37 -15
  34. mapfolding-0.13.1.dist-info/METADATA +0 -154
  35. {mapfolding-0.13.1.dist-info → mapfolding-0.14.0.dist-info}/WHEEL +0 -0
  36. {mapfolding-0.13.1.dist-info → mapfolding-0.14.0.dist-info}/entry_points.txt +0 -0
  37. {mapfolding-0.13.1.dist-info → mapfolding-0.14.0.dist-info}/licenses/LICENSE +0 -0
  38. {mapfolding-0.13.1.dist-info → mapfolding-0.14.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,122 @@
1
+ from collections.abc import Iterable
2
+ from hunterMakesPy import raiseIfNone
3
+
4
+ class BasicMeanderProblem:
5
+
6
+ def __init__(self, remainingBridges: int) -> None:
7
+ self.remainingBridges = remainingBridges
8
+ self.archStateLimit = 1 << (2 + (2 * (remainingBridges + 1)))
9
+ self.bridgesTotalIsOdd = (remainingBridges & 1) == 1
10
+
11
+ def initializeA005316(self) -> list[int]:
12
+ if self.bridgesTotalIsOdd:
13
+ bitPattern = (1 << 2) | 1
14
+ bitPattern <<= 2
15
+ return [bitPattern | 1 << 1]
16
+ else:
17
+ bitPattern = (1 << 2) | 1
18
+ return [bitPattern | bitPattern << 1]
19
+
20
+ def initializeA000682(self) -> list[int]:
21
+ initialStatesList: list[int] = []
22
+ bitPattern = 1 if self.bridgesTotalIsOdd else ((1 << 2) | 1)
23
+
24
+ packedState = bitPattern | bitPattern << 1
25
+ while packedState < self.archStateLimit:
26
+ initialStatesList.append(packedState)
27
+ bitPattern = ((bitPattern << 2) | 1) << 2 | 1
28
+ packedState = bitPattern | bitPattern << 1
29
+
30
+ return initialStatesList
31
+
32
+ def enumerate(self, packedState: int) -> list[int]: # noqa: C901
33
+ bitMask = 0x5555555555555555
34
+ bitWidth = 64
35
+ while bitMask < packedState:
36
+ bitMask |= bitMask << bitWidth
37
+ bitWidth += bitWidth
38
+ lower: int = packedState & bitMask
39
+ upper: int = (packedState - lower) >> 1
40
+ nextStatesList: list[int] = []
41
+
42
+ if lower != 1:
43
+ nextState: int = (lower >> 2 | (((upper << 2) ^ (1 if (lower & 1) == 0 else 0)) << 1))
44
+ if nextState < self.archStateLimit:
45
+ nextStatesList.append(nextState)
46
+
47
+ if upper != 1:
48
+ nextState = (((lower << 2) ^ (1 if (upper & 1) == 0 else 0)) | (upper >> 2) << 1)
49
+ if nextState < self.archStateLimit:
50
+ nextStatesList.append(nextState)
51
+
52
+ nextState = ((lower << 2) | 1 | ((upper << 2) | 1) << 1)
53
+ if nextState < self.archStateLimit:
54
+ nextStatesList.append(nextState)
55
+
56
+ if lower != 1 and upper != 1 and ((lower & 1) == 0 or (upper & 1) == 0):
57
+ if (lower & 1) == 0 and (upper & 1) == 1:
58
+ archBalance = 0
59
+ bitPosition = 1
60
+ while archBalance >= 0:
61
+ bitPosition <<= 2
62
+ archBalance += 1 if (lower & bitPosition) == 0 else -1
63
+ lower ^= bitPosition
64
+ if (upper & 1) == 0 and (lower & 1) == 1:
65
+ archBalance = 0
66
+ bitPosition = 1
67
+ while archBalance >= 0:
68
+ bitPosition <<= 2
69
+ archBalance += 1 if (upper & bitPosition) == 0 else -1
70
+ upper ^= bitPosition
71
+ nextState = (lower >> 2 | (upper >> 2) << 1)
72
+ if nextState < self.archStateLimit:
73
+ nextStatesList.append(nextState)
74
+
75
+ return nextStatesList
76
+
77
+ class SimpleProcessor:
78
+
79
+ def __init__(self) -> None:
80
+ self.createStateMachine: type | None = None
81
+ self.totalTransitions = 0
82
+
83
+ def setCreateStateMachine(self, stateMachineCreator: type) -> None:
84
+ self.createStateMachine = stateMachineCreator
85
+
86
+ def process(self, bridgesCount: int, initialStates: Iterable[int]) -> int:
87
+ stateCounts: list[tuple[int, int]] = [(state, 1) for state in initialStates]
88
+
89
+ self.createStateMachine = raiseIfNone(self.createStateMachine, "State machine creator must be set before processing.")
90
+ bridgesRemaining: int = bridgesCount
91
+ while bridgesRemaining > 0:
92
+ bridgesRemaining -= 1
93
+ stateCounts = self._accumulate(self.createStateMachine(bridgesRemaining), stateCounts)
94
+
95
+ return sum(count for state, count in stateCounts)
96
+
97
+ def _accumulate(self, layer: BasicMeanderProblem, previousCounts: list[tuple[int, int]]) -> list[tuple[int, int]]:
98
+ stateCountsDict: dict[int, int] = {}
99
+ transitions: int = 0
100
+
101
+ for state, count in previousCounts:
102
+ for nextState in layer.enumerate(state):
103
+ if nextState in stateCountsDict:
104
+ stateCountsDict[nextState] += count
105
+ else:
106
+ stateCountsDict[nextState] = count
107
+ transitions += 1
108
+
109
+ self.totalTransitions += transitions
110
+ return list(stateCountsDict.items())
111
+
112
+ def A005316(n: int) -> int:
113
+ processor = SimpleProcessor()
114
+ processor.setCreateStateMachine(BasicMeanderProblem)
115
+ meanderProblem = BasicMeanderProblem(n)
116
+ return processor.process(n, meanderProblem.initializeA005316())
117
+
118
+ def A000682(n: int) -> int:
119
+ processor = SimpleProcessor()
120
+ processor.setCreateStateMachine(BasicMeanderProblem)
121
+ meanderProblem = BasicMeanderProblem(n-1)
122
+ return processor.process(n-1, meanderProblem.initializeA000682())
@@ -0,0 +1,79 @@
1
+ def count(bridges: int, dictionaryCurveLocationsKnown: dict[int, int]) -> int:
2
+ while bridges > 0:
3
+ bridges -= 1
4
+ curveLocationsMAXIMUM = 1 << (2 * bridges + 4)
5
+ dictionaryCurveLocationsDiscovered: dict[int, int] = {}
6
+
7
+ for curveLocations, distinctCrossings in dictionaryCurveLocationsKnown.items():
8
+ bifurcationOdd = curveLocations & 0x5555555555555555555555555555555555555555555555555555555555555555
9
+ bifurcationEven = (curveLocations ^ bifurcationOdd) >> 1
10
+
11
+ bifurcationOddHasCurves = bifurcationOdd != 1
12
+ bifurcationEvenHasCurves = bifurcationEven != 1
13
+ bifurcationOddFinalZero = not bifurcationOdd & 1
14
+ bifurcationEvenFinalZero = not bifurcationEven & 1
15
+
16
+ if bifurcationOddHasCurves:
17
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
18
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
19
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
20
+
21
+ if bifurcationEvenHasCurves:
22
+ curveLocationAnalysis = (bifurcationEven >> 1) | (bifurcationOdd << 2) | bifurcationEvenFinalZero
23
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
24
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
25
+
26
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
27
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
28
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
29
+
30
+ if bifurcationOddHasCurves and bifurcationEvenHasCurves and (bifurcationOddFinalZero or bifurcationEvenFinalZero):
31
+ XOrHere2makePair = 0b1
32
+ findUnpairedBinary1 = 0
33
+ if bifurcationOddFinalZero and not bifurcationEvenFinalZero:
34
+ while findUnpairedBinary1 >= 0:
35
+ XOrHere2makePair <<= 2
36
+ findUnpairedBinary1 += 1 if (bifurcationOdd & XOrHere2makePair) == 0 else -1
37
+ bifurcationOdd ^= XOrHere2makePair
38
+
39
+ elif bifurcationEvenFinalZero and not bifurcationOddFinalZero:
40
+ while findUnpairedBinary1 >= 0:
41
+ XOrHere2makePair <<= 2
42
+ findUnpairedBinary1 += 1 if (bifurcationEven & XOrHere2makePair) == 0 else -1
43
+ bifurcationEven ^= XOrHere2makePair
44
+
45
+ curveLocationAnalysis = (bifurcationOdd >> 2) | ((bifurcationEven >> 2) << 1)
46
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
47
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
48
+
49
+ dictionaryCurveLocationsKnown = dictionaryCurveLocationsDiscovered
50
+
51
+ return sum(dictionaryCurveLocationsKnown.values())
52
+
53
+ def initializeA005316(n: int) -> dict[int, int]:
54
+ if n & 1:
55
+ return {22: 1}
56
+ else:
57
+ return {15: 1}
58
+
59
+ def initializeA000682(n: int) -> dict[int, int]:
60
+ stateToCount: dict[int, int] = {}
61
+
62
+ curveLocationsMAXIMUM = 1 << (2 * n + 4)
63
+
64
+ bitPattern = 5 - (n & 1) * 4
65
+
66
+ packedState = bitPattern | (bitPattern << 1)
67
+ while packedState < curveLocationsMAXIMUM:
68
+ stateToCount[packedState] = 1
69
+ bitPattern = ((bitPattern << 4) | 0b0101)
70
+ packedState = bitPattern | (bitPattern << 1)
71
+
72
+ return stateToCount
73
+
74
+ def A005316(n: int) -> int:
75
+ return count(n, initializeA005316(n))
76
+
77
+ def A000682(n: int) -> int:
78
+ return count(n - 1, initializeA000682(n - 1))
79
+
@@ -0,0 +1,97 @@
1
+ bifurcationOddLocator = 0x55555555555555555555555555555555
2
+ bitWidth = 1 << (bifurcationOddLocator.bit_length() - 1).bit_length()
3
+
4
+ def count(bridges: int, dictionaryCurveLocationsKnown: dict[int, int]) -> int:
5
+ while bridges > 0:
6
+ bridges -= 1
7
+ curveLocationsMAXIMUM = 1 << (2 + (2 * (bridges + 1)))
8
+
9
+ dictionaryCurveLocationsDiscovered: dict[int, int] = {}
10
+
11
+ for curveLocations, distinctCrossings in dictionaryCurveLocationsKnown.items():
12
+ global bifurcationOddLocator, bitWidth # noqa: PLW0603
13
+
14
+ if curveLocations > bifurcationOddLocator:
15
+ while curveLocations > bifurcationOddLocator:
16
+ bifurcationOddLocator |= bifurcationOddLocator << bitWidth
17
+ bitWidth <<= 1
18
+
19
+ bifurcationOdd = curveLocations & bifurcationOddLocator
20
+ bifurcationEven = (curveLocations ^ bifurcationOdd) >> 1
21
+
22
+ bifurcationOddHasCurves = bifurcationOdd != 1
23
+ bifurcationEvenHasCurves = bifurcationEven != 1
24
+ bifurcationOddFinalZero = (bifurcationOdd & 1) == 0
25
+ bifurcationEvenFinalZero = (bifurcationEven & 1) == 0
26
+
27
+ if bifurcationOddHasCurves:
28
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
29
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
30
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
31
+
32
+ if bifurcationEvenHasCurves:
33
+ curveLocationAnalysis = (bifurcationEven >> 1) | ((bifurcationOdd << 2) | bifurcationEvenFinalZero)
34
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
35
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
36
+
37
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
38
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
39
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
40
+
41
+ if bifurcationOddHasCurves and bifurcationEvenHasCurves and (bifurcationOddFinalZero or bifurcationEvenFinalZero):
42
+ if bifurcationOddFinalZero and not bifurcationEvenFinalZero:
43
+ Z0Z_idk = 0
44
+ Z0Z_indexIDK = 1
45
+ while Z0Z_idk >= 0:
46
+ Z0Z_indexIDK <<= 2
47
+ Z0Z_idk += 1 if (bifurcationOdd & Z0Z_indexIDK) == 0 else -1
48
+ bifurcationOdd ^= Z0Z_indexIDK
49
+
50
+ if bifurcationEvenFinalZero and not bifurcationOddFinalZero:
51
+ Z0Z_idk = 0
52
+ Z0Z_indexIDK = 1
53
+ while Z0Z_idk >= 0:
54
+ Z0Z_indexIDK <<= 2
55
+ Z0Z_idk += 1 if (bifurcationEven & Z0Z_indexIDK) == 0 else -1
56
+ bifurcationEven ^= Z0Z_indexIDK
57
+
58
+ curveLocationAnalysis = (bifurcationOdd >> 2) | ((bifurcationEven >> 2) << 1)
59
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
60
+ dictionaryCurveLocationsDiscovered[curveLocationAnalysis] = dictionaryCurveLocationsDiscovered.get(curveLocationAnalysis, 0) + distinctCrossings
61
+
62
+ dictionaryCurveLocationsKnown = dictionaryCurveLocationsDiscovered
63
+
64
+ return sum(dictionaryCurveLocationsKnown.values())
65
+
66
+ def initializeA005316(n: int) -> dict[int, int]:
67
+ bridgesTotalIsOdd = (n & 1) == 1
68
+ if bridgesTotalIsOdd:
69
+ arrayBitPattern = (1 << 2) | 1
70
+ arrayBitPattern <<= 2
71
+ initialState = arrayBitPattern | 1 << 1
72
+ return {initialState: 1}
73
+ else:
74
+ arrayBitPattern = (1 << 2) | 1
75
+ initialState = arrayBitPattern | arrayBitPattern << 1
76
+ return {initialState: 1}
77
+
78
+ def initializeA000682(n: int) -> dict[int, int]:
79
+ bridgesTotalIsOdd = (n & 1) == 1
80
+ archStateLimit = 1 << (2 + (2 * (n + 1)))
81
+
82
+ dictionaryStateToTotal: dict[int, int] = {}
83
+ arrayBitPattern = 1 if bridgesTotalIsOdd else ((1 << 2) | 1)
84
+
85
+ arrayPackedState = arrayBitPattern | arrayBitPattern << 1
86
+ while arrayPackedState < archStateLimit:
87
+ dictionaryStateToTotal[arrayPackedState] = 1
88
+ arrayBitPattern = ((arrayBitPattern << 2) | 1) << 2 | 1
89
+ arrayPackedState = arrayBitPattern | arrayBitPattern << 1
90
+
91
+ return dictionaryStateToTotal
92
+
93
+ def A005316(n: int) -> int:
94
+ return count(n, initializeA005316(n))
95
+
96
+ def A000682(n: int) -> int:
97
+ return count(n - 1, initializeA000682(n - 1))
@@ -0,0 +1,118 @@
1
+ import redis
2
+
3
+ def count(bridges: int, curveLocationsKnown: dict[int, int]) -> int:
4
+ # Initialize Redis connection
5
+ redisClient = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
6
+
7
+ # Load initial data into Redis
8
+ redisClient.flushdb()
9
+ for key, value in curveLocationsKnown.items():
10
+ redisClient.set(f"known:{key}", str(value))
11
+
12
+ while bridges > 0:
13
+ bridges -= 1
14
+ curveLocationsMAXIMUM = 1 << (2 * bridges + 4)
15
+
16
+ # Clear discovered data in Redis
17
+ for key in redisClient.scan_iter(match="discovered:*"):
18
+ redisClient.delete(key)
19
+
20
+ def storeCurveLocations(curveLocationAnalysis: int, distinctCrossings: int,
21
+ curveLocationsMAXIMUM: int = curveLocationsMAXIMUM,
22
+ redisClient: redis.Redis = redisClient) -> None:
23
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
24
+ keyName = f"discovered:{curveLocationAnalysis}"
25
+ existingValue = redisClient.get(keyName)
26
+ if existingValue is not None:
27
+ newValue = int(existingValue) + distinctCrossings
28
+ else:
29
+ newValue = distinctCrossings
30
+ redisClient.set(keyName, str(newValue))
31
+
32
+ # Process all known curve locations from Redis
33
+ for keyName in redisClient.scan_iter(match="known:*"):
34
+ curveLocations = int(str(keyName).split(":")[1])
35
+ distinctCrossings = int(str(redisClient.get(keyName)))
36
+
37
+ bifurcationOdd = curveLocations & 0x5555555555555555555555555555555555555555555555555555555555555555
38
+ bifurcationEven = (curveLocations ^ bifurcationOdd) >> 1
39
+
40
+ bifurcationOddHasCurves = bifurcationOdd != 1
41
+ bifurcationEvenHasCurves = bifurcationEven != 1
42
+ bifurcationOddFinalZero = not bifurcationOdd & 1
43
+ bifurcationEvenFinalZero = not bifurcationEven & 1
44
+
45
+ if bifurcationOddHasCurves:
46
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
47
+ storeCurveLocations(curveLocationAnalysis, distinctCrossings)
48
+
49
+ if bifurcationEvenHasCurves:
50
+ curveLocationAnalysis = (bifurcationEven >> 1) | (bifurcationOdd << 2) | bifurcationEvenFinalZero
51
+ storeCurveLocations(curveLocationAnalysis, distinctCrossings)
52
+
53
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
54
+ storeCurveLocations(curveLocationAnalysis, distinctCrossings)
55
+
56
+ if bifurcationOddHasCurves and bifurcationEvenHasCurves and (bifurcationOddFinalZero or bifurcationEvenFinalZero):
57
+ XOrHere2makePair = 0b1
58
+ findUnpairedBinary1 = 0
59
+ if bifurcationOddFinalZero and not bifurcationEvenFinalZero:
60
+ while findUnpairedBinary1 >= 0:
61
+ XOrHere2makePair <<= 2
62
+ findUnpairedBinary1 += 1 if (bifurcationOdd & XOrHere2makePair) == 0 else -1
63
+ bifurcationOdd ^= XOrHere2makePair
64
+
65
+ elif bifurcationEvenFinalZero and not bifurcationOddFinalZero:
66
+ while findUnpairedBinary1 >= 0:
67
+ XOrHere2makePair <<= 2
68
+ findUnpairedBinary1 += 1 if (bifurcationEven & XOrHere2makePair) == 0 else -1
69
+ bifurcationEven ^= XOrHere2makePair
70
+
71
+ curveLocationAnalysis = (bifurcationOdd >> 2) | ((bifurcationEven >> 2) << 1)
72
+ storeCurveLocations(curveLocationAnalysis, distinctCrossings)
73
+
74
+ # Move discovered data to known for next iteration
75
+ for keyName in redisClient.scan_iter(match="known:*"):
76
+ redisClient.delete(str(keyName))
77
+
78
+ for keyName in redisClient.scan_iter(match="discovered:*"):
79
+ newKeyName = str(keyName).replace("discovered:", "known:")
80
+ value = redisClient.get(str(keyName))
81
+ redisClient.set(newKeyName, str(value))
82
+ redisClient.delete(str(keyName))
83
+
84
+ # Calculate final sum from Redis
85
+ totalResult = 0
86
+ for keyName in redisClient.scan_iter(match="known:*"):
87
+ value = int(str(redisClient.get(str(keyName))))
88
+ totalResult += value
89
+
90
+ return totalResult
91
+
92
+ def initializeA005316(n: int) -> dict[int, int]:
93
+ if n & 1:
94
+ return {22: 1}
95
+ else:
96
+ return {15: 1}
97
+
98
+ def initializeA000682(n: int) -> dict[int, int]:
99
+ stateToCount: dict[int, int] = {}
100
+
101
+ curveLocationsMAXIMUM = 1 << (2 * n + 4)
102
+
103
+ bitPattern = 5 - (n & 1) * 4
104
+
105
+ packedState = bitPattern | (bitPattern << 1)
106
+ while packedState < curveLocationsMAXIMUM:
107
+ stateToCount[packedState] = 1
108
+ bitPattern = ((bitPattern << 4) | 0b0101)
109
+ packedState = bitPattern | (bitPattern << 1)
110
+
111
+ return stateToCount
112
+
113
+ def A005316(n: int) -> int:
114
+ return count(n, initializeA005316(n))
115
+
116
+ def A000682(n: int) -> int:
117
+ return count(n - 1, initializeA000682(n - 1))
118
+
@@ -0,0 +1,169 @@
1
+ from pathlib import Path
2
+ import shutil
3
+ import threading
4
+
5
+ pathRoot = Path.cwd() / 'curves'
6
+
7
+ curveMaximum: dict[int, int] = {0: 16,
8
+ 1: 64,
9
+ 2: 256,
10
+ 3: 1024,
11
+ 4: 4096,
12
+ 5: 16384,
13
+ 6: 65536,
14
+ 7: 262144,
15
+ 8: 1048576,
16
+ 9: 4194304,
17
+ 10: 16777216,
18
+ 11: 67108864,
19
+ 12: 268435456,
20
+ 13: 1073741824,
21
+ 14: 4294967296,
22
+ 15: 17179869184,
23
+ 16: 68719476736,
24
+ 17: 274877906944,
25
+ 18: 1099511627776,
26
+ 19: 4398046511104,
27
+ 20: 17592186044416,
28
+ 21: 70368744177664,
29
+ 22: 281474976710656,
30
+ 23: 1125899906842624,
31
+ 24: 4503599627370496,
32
+ 25: 18014398509481984,
33
+ 26: 72057594037927936,
34
+ 27: 288230376151711744,
35
+ 28: 1152921504606846976,
36
+ 29: 4611686018427387904,
37
+ 30: 18446744073709551616,
38
+ 31: 73786976294838206464,
39
+ 32: 295147905179352825856,
40
+ 33: 1180591620717411303424,
41
+ 34: 4722366482869645213696,
42
+ 35: 18889465931478580854784,
43
+ 36: 75557863725914323419136,
44
+ 37: 302231454903657293676544,
45
+ 38: 1208925819614629174706176,
46
+ 39: 4835703278458516698824704,
47
+ 40: 19342813113834066795298816,
48
+ 41: 77371252455336267181195264,
49
+ 42: 309485009821345068724781056,
50
+ 43: 1237940039285380274899124224,
51
+ 44: 4951760157141521099596496896,
52
+ 45: 19807040628566084398385987584,
53
+ 46: 79228162514264337593543950336,
54
+ 47: 316912650057057350374175801344,
55
+ 48: 1267650600228229401496703205376,
56
+ 49: 5070602400912917605986812821504,
57
+ 50: 20282409603651670423947251286016,
58
+ 51: 81129638414606681695789005144064,
59
+ 52: 324518553658426726783156020576256,
60
+ 53: 1298074214633706907132624082305024,
61
+ 54: 5192296858534827628530496329220096,
62
+ 55: 20769187434139310514121985316880384,
63
+ 56: 83076749736557242056487941267521536,
64
+ 57: 332306998946228968225951765070086144,
65
+ 58: 1329227995784915872903807060280344576,
66
+ 59: 5316911983139663491615228241121378304,
67
+ 60: 21267647932558653966460912964485513216,
68
+ 61: 85070591730234615865843651857942052864}
69
+
70
+ def buildDictionaryCurveLocations(bridges: int) -> dict[int, int]:
71
+ """Wait for the writing to finish."""
72
+ dictionaryCurveLocations: dict[int, int] = {}
73
+ for curveLocation in Path(pathRoot, str(bridges)).glob('*'):
74
+ dictionaryCurveLocations[int(curveLocation.stem)] = eval(curveLocation.read_text().strip().rstrip('+')) # noqa: S307
75
+ return dictionaryCurveLocations
76
+
77
+ def recordAnalysis(bridges: int, curveLocationAnalysis: int, distinctCrossings: int) -> None:
78
+ """Record and building system should be fluid: it will write to disk when needed."""
79
+ def _record() -> None:
80
+ if curveLocationAnalysis < curveMaximum[bridges]:
81
+ with Path(pathRoot, str(bridges), str(curveLocationAnalysis)).open('a') as appendStream:
82
+ appendStream.write(f"{distinctCrossings}+")
83
+
84
+ bookkeeper = threading.Thread(target=_record)
85
+ bookkeeper.daemon = True
86
+ bookkeeper.start()
87
+
88
+ def analyzeCurves(bridges: int, curveLocations: int, distinctCrossings: int) -> None:
89
+ bifurcationOdd = curveLocations & 0x5555555555555555555555555555555555555555555555555555555555555555
90
+ bifurcationEven = (curveLocations ^ bifurcationOdd) >> 1
91
+
92
+ bifurcationOddHasCurves = bifurcationOdd != 1
93
+ bifurcationEvenHasCurves = bifurcationEven != 1
94
+ bifurcationOddFinalZero = not bifurcationOdd & 1
95
+ bifurcationEvenFinalZero = not bifurcationEven & 1
96
+
97
+ if bifurcationOddHasCurves:
98
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
99
+ recordAnalysis(bridges, curveLocationAnalysis, distinctCrossings)
100
+
101
+ if bifurcationEvenHasCurves:
102
+ curveLocationAnalysis = (bifurcationEven >> 1) | (bifurcationOdd << 2) | bifurcationEvenFinalZero
103
+ recordAnalysis(bridges, curveLocationAnalysis, distinctCrossings)
104
+
105
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
106
+ recordAnalysis(bridges, curveLocationAnalysis, distinctCrossings)
107
+
108
+ if bifurcationOddHasCurves and bifurcationEvenHasCurves and (bifurcationOddFinalZero or bifurcationEvenFinalZero):
109
+ XOrHere2makePair = 0b1
110
+ findUnpairedBinary1 = 0
111
+ if bifurcationOddFinalZero and not bifurcationEvenFinalZero:
112
+ while findUnpairedBinary1 >= 0:
113
+ XOrHere2makePair <<= 2
114
+ findUnpairedBinary1 += 1 if (bifurcationOdd & XOrHere2makePair) == 0 else -1
115
+ bifurcationOdd ^= XOrHere2makePair
116
+
117
+ elif bifurcationEvenFinalZero and not bifurcationOddFinalZero:
118
+ while findUnpairedBinary1 >= 0:
119
+ XOrHere2makePair <<= 2
120
+ findUnpairedBinary1 += 1 if (bifurcationEven & XOrHere2makePair) == 0 else -1
121
+ bifurcationEven ^= XOrHere2makePair
122
+
123
+ curveLocationAnalysis = (bifurcationOdd >> 2) | ((bifurcationEven >> 2) << 1)
124
+ recordAnalysis(bridges, curveLocationAnalysis, distinctCrossings)
125
+
126
+ def count(bridges: int, dictionaryCurveLocations: dict[int, int]) -> int:
127
+ shutil.rmtree(pathRoot, ignore_errors=True)
128
+ pathRoot.mkdir(exist_ok=True)
129
+ for n in range(bridges):
130
+ Path(pathRoot, str(n)).mkdir(exist_ok=True)
131
+
132
+ while bridges > 0:
133
+ bridges -= 1
134
+
135
+ for curveLocations, distinctCrossings in dictionaryCurveLocations.items():
136
+ """This is now ready for concurrency."""
137
+ analyzeCurves(bridges, curveLocations, distinctCrossings)
138
+
139
+ dictionaryCurveLocations = buildDictionaryCurveLocations(bridges)
140
+
141
+ return sum(dictionaryCurveLocations.values())
142
+
143
+ def initializeA005316(n: int) -> dict[int, int]:
144
+ if n & 1:
145
+ return {22: 1}
146
+ else:
147
+ return {15: 1}
148
+
149
+ def initializeA000682(n: int) -> dict[int, int]:
150
+ stateToCount: dict[int, int] = {}
151
+
152
+ curveLocationsMAXIMUM = 1 << (2 * n + 4)
153
+
154
+ bitPattern = 5 - (n & 1) * 4
155
+
156
+ packedState = bitPattern | (bitPattern << 1)
157
+ while packedState < curveLocationsMAXIMUM:
158
+ stateToCount[packedState] = 1
159
+ bitPattern = ((bitPattern << 4) | 0b0101)
160
+ packedState = bitPattern | (bitPattern << 1)
161
+
162
+ return stateToCount
163
+
164
+ def A005316(n: int) -> int:
165
+ return count(n, initializeA005316(n))
166
+
167
+ def A000682(n: int) -> int:
168
+ return count(n - 1, initializeA000682(n - 1))
169
+
@@ -2,16 +2,12 @@
2
2
  Ported from the Java version by Sean A. Irvine:
3
3
  https://github.com/archmageirvine/joeis/blob/80e3e844b11f149704acbab520bc3a3a25ac34ff/src/irvine/oeis/a001/A001415.java
4
4
 
5
- This implementation is a conversion from a well-known Java implementation of Lunnon's algorithm
6
- by Sean A. Irvine, a contributor to the OEIS project. It provides a clean, procedural implementation
7
- with straightforward variable naming and control flow that may be more approachable for
8
- programmers familiar with modern languages.
5
+ This implementation is a Python version of a Java implementation of Lunnon's algorithm by Sean A. Irvine.
9
6
 
10
7
  Key characteristics:
11
- - Clear variable naming following modern programming conventions
12
- - Procedural implementation style similar to Java but adapted for Python
13
- - Follows the same algorithmic structure as Lunnon's original but with cleaner organization
14
- - Uses primitive Python data structures (lists) without NumPy dependencies
8
+ - Identifiers tend to match Irvine.
9
+ - A procedural paradigm more similar to Lunnon and unlike Irvine's object-oriented implementation.
10
+ - Only primitive Python data structures.
15
11
 
16
12
  Citation: https://github.com/hunterhogan/mapFolding/blob/134f2e6ecdf59fb6f6829c775475544a6aaaa800/citations/jOEIS.bibtex
17
13
  """
@@ -0,0 +1,65 @@
1
+ from mapFolding._oeisFormulas.matrixMeandersAnnex import curveMaximum as curveMaximum
2
+
3
+ dictionaryCurveLocations: dict[int, int] = {}
4
+
5
+ def getCurveLocations() -> dict[int, int]:
6
+ global dictionaryCurveLocations # noqa: PLW0603
7
+ sherpa = dictionaryCurveLocations.copy()
8
+ dictionaryCurveLocations = {}
9
+ return sherpa
10
+
11
+ def recordAnalysis(curveLocationAnalysis: int, curveLocationsMAXIMUM: int, distinctCrossings: int) -> None:
12
+ if curveLocationAnalysis < curveLocationsMAXIMUM:
13
+ dictionaryCurveLocations[curveLocationAnalysis] = dictionaryCurveLocations.get(curveLocationAnalysis, 0) + distinctCrossings
14
+
15
+ def initializeCurveLocations(startingCurveLocations: dict[int, int]) -> None:
16
+ global dictionaryCurveLocations # noqa: PLW0603
17
+ dictionaryCurveLocations = startingCurveLocations.copy()
18
+
19
+ def count(bridges: int, startingCurveLocations: dict[int, int]) -> int:
20
+ initializeCurveLocations(startingCurveLocations)
21
+
22
+ while bridges > 0:
23
+ bridges -= 1
24
+ curveLocationsMAXIMUM, bifurcationEvenLocator, bifurcationOddLocator = curveMaximum[bridges]
25
+
26
+ for curveLocations, distinctCrossings in getCurveLocations().items():
27
+ bifurcationEven = (curveLocations & bifurcationEvenLocator) >> 1
28
+ bifurcationOdd = curveLocations & bifurcationOddLocator
29
+
30
+ bifurcationEvenFinalZero = (bifurcationEven & 0b1) == 0
31
+ bifurcationEvenHasCurves = bifurcationEven != 1
32
+ bifurcationOddFinalZero = (bifurcationOdd & 0b1) == 0
33
+ bifurcationOddHasCurves = bifurcationOdd != 1
34
+
35
+ if bifurcationEvenHasCurves:
36
+ curveLocationAnalysis = (bifurcationEven >> 1) | (bifurcationOdd << 2) | bifurcationEvenFinalZero
37
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
38
+
39
+ if bifurcationOddHasCurves:
40
+ curveLocationAnalysis = (bifurcationOdd >> 2) | (bifurcationEven << 3) | (bifurcationOddFinalZero << 1)
41
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
42
+
43
+ curveLocationAnalysis = ((bifurcationOdd | (bifurcationEven << 1)) << 2) | 3
44
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
45
+
46
+ if bifurcationEvenHasCurves and bifurcationOddHasCurves and (bifurcationEvenFinalZero or bifurcationOddFinalZero):
47
+ XOrHere2makePair = 0b1
48
+ findUnpairedBinary1 = 0
49
+
50
+ if bifurcationEvenFinalZero and not bifurcationOddFinalZero:
51
+ while findUnpairedBinary1 >= 0:
52
+ XOrHere2makePair <<= 2
53
+ findUnpairedBinary1 += 1 if (bifurcationEven & XOrHere2makePair) == 0 else -1
54
+ bifurcationEven ^= XOrHere2makePair
55
+
56
+ elif bifurcationOddFinalZero and not bifurcationEvenFinalZero:
57
+ while findUnpairedBinary1 >= 0:
58
+ XOrHere2makePair <<= 2
59
+ findUnpairedBinary1 += 1 if (bifurcationOdd & XOrHere2makePair) == 0 else -1
60
+ bifurcationOdd ^= XOrHere2makePair
61
+
62
+ curveLocationAnalysis = ((bifurcationEven >> 2) << 1) | (bifurcationOdd >> 2)
63
+ recordAnalysis(curveLocationAnalysis, curveLocationsMAXIMUM, distinctCrossings)
64
+
65
+ return sum(getCurveLocations().values())