mapFolding 0.3.12__py3-none-any.whl → 0.4.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.
Files changed (46) hide show
  1. mapFolding/__init__.py +40 -38
  2. mapFolding/basecamp.py +50 -50
  3. mapFolding/beDRY.py +336 -336
  4. mapFolding/oeis.py +262 -262
  5. mapFolding/reference/flattened.py +294 -293
  6. mapFolding/reference/hunterNumba.py +126 -126
  7. mapFolding/reference/irvineJavaPort.py +99 -99
  8. mapFolding/reference/jax.py +153 -153
  9. mapFolding/reference/lunnan.py +148 -148
  10. mapFolding/reference/lunnanNumpy.py +115 -115
  11. mapFolding/reference/lunnanWhile.py +114 -114
  12. mapFolding/reference/rotatedEntryPoint.py +183 -183
  13. mapFolding/reference/total_countPlus1vsPlusN.py +203 -203
  14. mapFolding/someAssemblyRequired/__init__.py +5 -1
  15. mapFolding/someAssemblyRequired/getLLVMforNoReason.py +12 -12
  16. mapFolding/someAssemblyRequired/makeJob.py +46 -52
  17. mapFolding/someAssemblyRequired/synthesizeModuleJAX.py +17 -17
  18. mapFolding/someAssemblyRequired/synthesizeNumba.py +343 -633
  19. mapFolding/someAssemblyRequired/synthesizeNumbaGeneralized.py +325 -0
  20. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +173 -0
  21. mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +77 -0
  22. mapFolding/syntheticModules/__init__.py +0 -0
  23. mapFolding/syntheticModules/numba_countInitialize.py +4 -4
  24. mapFolding/syntheticModules/numba_countParallel.py +4 -4
  25. mapFolding/syntheticModules/numba_countSequential.py +4 -4
  26. mapFolding/syntheticModules/numba_doTheNeedful.py +7 -7
  27. mapFolding/theDao.py +165 -165
  28. mapFolding/theSSOT.py +177 -173
  29. mapFolding/theSSOTnumba.py +90 -74
  30. mapFolding-0.4.1.dist-info/METADATA +154 -0
  31. mapFolding-0.4.1.dist-info/RECORD +42 -0
  32. tests/conftest.py +253 -129
  33. tests/test_computations.py +79 -0
  34. tests/test_oeis.py +76 -85
  35. tests/test_other.py +136 -224
  36. tests/test_tasks.py +19 -23
  37. tests/test_types.py +2 -2
  38. mapFolding/someAssemblyRequired/synthesizeNumbaHardcoding.py +0 -188
  39. mapFolding-0.3.12.dist-info/METADATA +0 -155
  40. mapFolding-0.3.12.dist-info/RECORD +0 -40
  41. tests/conftest_tmpRegistry.py +0 -62
  42. tests/conftest_uniformTests.py +0 -53
  43. {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/LICENSE +0 -0
  44. {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/WHEEL +0 -0
  45. {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/entry_points.txt +0 -0
  46. {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/top_level.txt +0 -0
mapFolding/oeis.py CHANGED
@@ -13,9 +13,9 @@ import urllib.response
13
13
  import warnings
14
14
 
15
15
  if TYPE_CHECKING:
16
- from typing import TypedDict
16
+ from typing import TypedDict
17
17
  else:
18
- TypedDict = dict
18
+ TypedDict = dict
19
19
 
20
20
  """
21
21
  Section: make `settingsOEIS`"""
@@ -23,217 +23,217 @@ Section: make `settingsOEIS`"""
23
23
  _pathCache = getPathPackage() / ".cache"
24
24
 
25
25
  class SettingsOEIS(TypedDict):
26
- description: str
27
- offset: int
28
- getMapShape: Callable[[int], List[int]]
29
- valuesBenchmark: List[int]
30
- valuesKnown: Dict[int, int]
31
- valuesTestParallelization: List[int]
32
- valuesTestValidation: List[int]
33
- valueUnknown: int
26
+ description: str
27
+ offset: int
28
+ getMapShape: Callable[[int], List[int]]
29
+ valuesBenchmark: List[int]
30
+ valuesKnown: Dict[int, int]
31
+ valuesTestParallelization: List[int]
32
+ valuesTestValidation: List[int]
33
+ valueUnknown: int
34
34
 
35
35
  settingsOEIShardcodedValues: Dict[str, Dict[str, Any]] = {
36
- 'A001415': {
37
- 'getMapShape': lambda n: sorted([2, n]),
38
- 'valuesBenchmark': [14],
39
- 'valuesTestParallelization': [*range(3, 7)],
40
- 'valuesTestValidation': [0, 1, random.randint(2, 9)],
41
- },
42
- 'A001416': {
43
- 'getMapShape': lambda n: sorted([3, n]),
44
- 'valuesBenchmark': [9],
45
- 'valuesTestParallelization': [*range(3, 5)],
46
- 'valuesTestValidation': [0, 1, random.randint(2, 6)],
47
- },
48
- 'A001417': {
49
- 'getMapShape': lambda n: [2] * n,
50
- 'valuesBenchmark': [6],
51
- 'valuesTestParallelization': [*range(2, 4)],
52
- 'valuesTestValidation': [0, 1, random.randint(2, 4)],
53
- },
54
- 'A195646': {
55
- 'getMapShape': lambda n: [3] * n,
56
- 'valuesBenchmark': [3],
57
- 'valuesTestParallelization': [*range(2, 3)],
58
- 'valuesTestValidation': [0, 1, 2],
59
- },
60
- 'A001418': {
61
- 'getMapShape': lambda n: [n, n],
62
- 'valuesBenchmark': [5],
63
- 'valuesTestParallelization': [*range(2, 4)],
64
- 'valuesTestValidation': [1, random.randint(2, 4)],
65
- },
36
+ 'A001415': {
37
+ 'getMapShape': lambda n: sorted([2, n]),
38
+ 'valuesBenchmark': [14],
39
+ 'valuesTestParallelization': [*range(3, 7)],
40
+ 'valuesTestValidation': [random.randint(2, 9)],
41
+ },
42
+ 'A001416': {
43
+ 'getMapShape': lambda n: sorted([3, n]),
44
+ 'valuesBenchmark': [9],
45
+ 'valuesTestParallelization': [*range(3, 5)],
46
+ 'valuesTestValidation': [random.randint(2, 6)],
47
+ },
48
+ 'A001417': {
49
+ 'getMapShape': lambda n: [2] * n,
50
+ 'valuesBenchmark': [6],
51
+ 'valuesTestParallelization': [*range(2, 4)],
52
+ 'valuesTestValidation': [random.randint(2, 4)],
53
+ },
54
+ 'A195646': {
55
+ 'getMapShape': lambda n: [3] * n,
56
+ 'valuesBenchmark': [3],
57
+ 'valuesTestParallelization': [*range(2, 3)],
58
+ 'valuesTestValidation': [2],
59
+ },
60
+ 'A001418': {
61
+ 'getMapShape': lambda n: [n, n],
62
+ 'valuesBenchmark': [5],
63
+ 'valuesTestParallelization': [*range(2, 4)],
64
+ 'valuesTestValidation': [random.randint(2, 4)],
65
+ },
66
66
  }
67
67
 
68
68
  oeisIDsImplemented: Final[List[str]] = sorted([oeisID.upper().strip() for oeisID in settingsOEIShardcodedValues.keys()])
69
69
  """Directly implemented OEIS IDs; standardized, e.g., 'A001415'."""
70
70
 
71
71
  def _validateOEISid(oeisIDcandidate: str) -> str:
72
- """
73
- Validates an OEIS sequence ID against implemented sequences.
74
-
75
- If the provided ID is recognized within the application's implemented
76
- OEIS sequences, the function returns the verified ID in uppercase.
77
- Otherwise, a KeyError is raised indicating that the sequence is not
78
- directly supported.
79
-
80
- Parameters:
81
- oeisIDcandidate: The OEIS sequence identifier to validate.
82
-
83
- Returns:
84
- oeisID: The validated and possibly modified OEIS sequence ID, if recognized.
85
-
86
- Raises:
87
- KeyError: If the provided sequence ID is not directly implemented.
88
- """
89
- if oeisIDcandidate in oeisIDsImplemented:
90
- return oeisIDcandidate
91
- else:
92
- oeisIDcleaned = str(oeisIDcandidate).upper().strip()
93
- if oeisIDcleaned in oeisIDsImplemented:
94
- return oeisIDcleaned
95
- else:
96
- raise KeyError(
97
- f"OEIS ID {oeisIDcandidate} is not directly implemented.\n"
98
- f"Available sequences:\n{_formatOEISsequenceInfo()}"
99
- )
72
+ """
73
+ Validates an OEIS sequence ID against implemented sequences.
74
+
75
+ If the provided ID is recognized within the application's implemented
76
+ OEIS sequences, the function returns the verified ID in uppercase.
77
+ Otherwise, a KeyError is raised indicating that the sequence is not
78
+ directly supported.
79
+
80
+ Parameters:
81
+ oeisIDcandidate: The OEIS sequence identifier to validate.
82
+
83
+ Returns:
84
+ oeisID: The validated and possibly modified OEIS sequence ID, if recognized.
85
+
86
+ Raises:
87
+ KeyError: If the provided sequence ID is not directly implemented.
88
+ """
89
+ if oeisIDcandidate in oeisIDsImplemented:
90
+ return oeisIDcandidate
91
+ else:
92
+ oeisIDcleaned = str(oeisIDcandidate).upper().strip()
93
+ if oeisIDcleaned in oeisIDsImplemented:
94
+ return oeisIDcleaned
95
+ else:
96
+ raise KeyError(
97
+ f"OEIS ID {oeisIDcandidate} is not directly implemented.\n"
98
+ f"Available sequences:\n{_formatOEISsequenceInfo()}"
99
+ )
100
100
 
101
101
  def _getFilenameOEISbFile(oeisID: str) -> str:
102
- oeisID = _validateOEISid(oeisID)
103
- return f"b{oeisID[1:]}.txt"
102
+ oeisID = _validateOEISid(oeisID)
103
+ return f"b{oeisID[1:]}.txt"
104
104
 
105
105
  def _parseBFileOEIS(OEISbFile: str, oeisID: str) -> Dict[int, int]:
106
- """
107
- Parses the content of an OEIS b-file for a given sequence ID.
108
- This function processes a multiline string representing an OEIS b-file and
109
- creates a dictionary mapping integer indices to their corresponding sequence
110
- values. The first line of the b-file is expected to contain a comment that
111
- matches the given sequence ID. If it does not match, a ValueError is raised.
112
-
113
- Parameters:
114
- OEISbFile: A multiline string representing an OEIS b-file.
115
- oeisID: The expected OEIS sequence identifier.
116
- Returns:
117
- OEISsequence: A dictionary where each key is an integer index `n` and
118
- each value is the sequence value `a(n)` corresponding to that index.
119
- Raises:
120
- ValueError: If the first line of the file does not indicate the expected
121
- sequence ID or if the content format is invalid.
122
- """
123
- bFileLines = OEISbFile.strip().splitlines()
124
- if not bFileLines.pop(0).startswith(f"# {oeisID}"):
125
- warnings.warn(f"Content does not match sequence {oeisID}")
126
- return {-1: -1}
127
-
128
- OEISsequence = {}
129
- for line in bFileLines:
130
- if line.startswith('#'):
131
- continue
132
- n, aOFn = map(int, line.split())
133
- OEISsequence[n] = aOFn
134
- return OEISsequence
106
+ """
107
+ Parses the content of an OEIS b-file for a given sequence ID.
108
+ This function processes a multiline string representing an OEIS b-file and
109
+ creates a dictionary mapping integer indices to their corresponding sequence
110
+ values. The first line of the b-file is expected to contain a comment that
111
+ matches the given sequence ID. If it does not match, a ValueError is raised.
112
+
113
+ Parameters:
114
+ OEISbFile: A multiline string representing an OEIS b-file.
115
+ oeisID: The expected OEIS sequence identifier.
116
+ Returns:
117
+ OEISsequence: A dictionary where each key is an integer index `n` and
118
+ each value is the sequence value `a(n)` corresponding to that index.
119
+ Raises:
120
+ ValueError: If the first line of the file does not indicate the expected
121
+ sequence ID or if the content format is invalid.
122
+ """
123
+ bFileLines = OEISbFile.strip().splitlines()
124
+ if not bFileLines.pop(0).startswith(f"# {oeisID}"):
125
+ warnings.warn(f"Content does not match sequence {oeisID}")
126
+ return {-1: -1}
127
+
128
+ OEISsequence = {}
129
+ for line in bFileLines:
130
+ if line.startswith('#'):
131
+ continue
132
+ n, aOFn = map(int, line.split())
133
+ OEISsequence[n] = aOFn
134
+ return OEISsequence
135
135
 
136
136
  def _getOEISofficial(pathFilenameCache: pathlib.Path, url: str) -> None | str:
137
- cacheDays = 7
138
- tryCache = False
139
- if pathFilenameCache.exists():
140
- fileAge = datetime.now() - datetime.fromtimestamp(pathFilenameCache.stat().st_mtime)
141
- tryCache = fileAge < timedelta(days=cacheDays)
142
-
143
- oeisInformation = None
144
- if tryCache:
145
- try:
146
- oeisInformation = pathFilenameCache.read_text()
147
- except IOError:
148
- tryCache = False
149
-
150
- if not tryCache:
151
- httpResponse: urllib.response.addinfourl = urllib.request.urlopen(url)
152
- oeisInformation = httpResponse.read().decode('utf-8')
153
- pathFilenameCache.parent.mkdir(parents=True, exist_ok=True)
154
- pathFilenameCache.write_text(oeisInformation)
155
-
156
- if not oeisInformation:
157
- warnings.warn(f"Failed to retrieve OEIS sequence information for {pathFilenameCache.stem}.")
158
-
159
- return oeisInformation
137
+ cacheDays = 7
138
+ tryCache = False
139
+ if pathFilenameCache.exists():
140
+ fileAge = datetime.now() - datetime.fromtimestamp(pathFilenameCache.stat().st_mtime)
141
+ tryCache = fileAge < timedelta(days=cacheDays)
142
+
143
+ oeisInformation = None
144
+ if tryCache:
145
+ try:
146
+ oeisInformation = pathFilenameCache.read_text()
147
+ except IOError:
148
+ tryCache = False
149
+
150
+ if not tryCache:
151
+ httpResponse: urllib.response.addinfourl = urllib.request.urlopen(url)
152
+ oeisInformation = httpResponse.read().decode('utf-8')
153
+ pathFilenameCache.parent.mkdir(parents=True, exist_ok=True)
154
+ pathFilenameCache.write_text(oeisInformation)
155
+
156
+ if not oeisInformation:
157
+ warnings.warn(f"Failed to retrieve OEIS sequence information for {pathFilenameCache.stem}.")
158
+
159
+ return oeisInformation
160
160
 
161
161
  def _getOEISidValues(oeisID: str) -> Dict[int, int]:
162
- """
163
- Retrieves the specified OEIS sequence as a dictionary mapping integer indices
164
- to their corresponding values.
165
- This function checks for a cached local copy of the sequence data, using it if
166
- it has not expired. Otherwise, it fetches the sequence data from the OEIS
167
- website and writes it to the cache. The parsed data is returned as a dictionary
168
- mapping each index to its sequence value.
169
-
170
- Parameters:
171
- oeisID: The identifier of the OEIS sequence to retrieve.
172
- Returns:
173
- OEISsequence: A dictionary where each key is an integer index, `n`, and each
174
- value is the corresponding "a(n)" from the OEIS entry.
175
- Raises:
176
- ValueError: If the cached or downloaded file format is invalid.
177
- IOError: If there is an error reading from or writing to the local cache.
178
- """
179
-
180
- pathFilenameCache = _pathCache / _getFilenameOEISbFile(oeisID)
181
- url = f"https://oeis.org/{oeisID}/{_getFilenameOEISbFile(oeisID)}"
182
-
183
- oeisInformation = _getOEISofficial(pathFilenameCache, url)
184
-
185
- if oeisInformation:
186
- return _parseBFileOEIS(oeisInformation, oeisID)
187
- return {-1: -1}
162
+ """
163
+ Retrieves the specified OEIS sequence as a dictionary mapping integer indices
164
+ to their corresponding values.
165
+ This function checks for a cached local copy of the sequence data, using it if
166
+ it has not expired. Otherwise, it fetches the sequence data from the OEIS
167
+ website and writes it to the cache. The parsed data is returned as a dictionary
168
+ mapping each index to its sequence value.
169
+
170
+ Parameters:
171
+ oeisID: The identifier of the OEIS sequence to retrieve.
172
+ Returns:
173
+ OEISsequence: A dictionary where each key is an integer index, `n`, and each
174
+ value is the corresponding "a(n)" from the OEIS entry.
175
+ Raises:
176
+ ValueError: If the cached or downloaded file format is invalid.
177
+ IOError: If there is an error reading from or writing to the local cache.
178
+ """
179
+
180
+ pathFilenameCache = _pathCache / _getFilenameOEISbFile(oeisID)
181
+ url = f"https://oeis.org/{oeisID}/{_getFilenameOEISbFile(oeisID)}"
182
+
183
+ oeisInformation = _getOEISofficial(pathFilenameCache, url)
184
+
185
+ if oeisInformation:
186
+ return _parseBFileOEIS(oeisInformation, oeisID)
187
+ return {-1: -1}
188
188
 
189
189
  def _getOEISidInformation(oeisID: str) -> Tuple[str, int]:
190
- oeisID = _validateOEISid(oeisID)
191
- pathFilenameCache = _pathCache / f"{oeisID}.txt"
192
- url = f"https://oeis.org/search?q=id:{oeisID}&fmt=text"
193
-
194
- oeisInformation = _getOEISofficial(pathFilenameCache, url)
195
-
196
- if not oeisInformation:
197
- return "Not found", -1
198
-
199
- description_parts = []
200
- offset = None
201
- for line in oeisInformation.splitlines():
202
- if line.startswith('%N'):
203
- parts = line.split()
204
- if parts[1] == oeisID:
205
- desc_part = ' '.join(parts[2:])
206
- description_parts.append(desc_part)
207
- elif line.startswith('%O'):
208
- parts = line.split()
209
- if parts[1] == oeisID:
210
- offset_str = parts[2].split(',')[0]
211
- offset = int(offset_str)
212
- if not description_parts:
213
- warnings.warn(f"No description found for {oeisID}")
214
- description_parts.append("No description found")
215
- if offset is None:
216
- warnings.warn(f"No offset found for {oeisID}")
217
- offset = -1
218
- description = ' '.join(description_parts)
219
- return description, offset
190
+ oeisID = _validateOEISid(oeisID)
191
+ pathFilenameCache = _pathCache / f"{oeisID}.txt"
192
+ url = f"https://oeis.org/search?q=id:{oeisID}&fmt=text"
193
+
194
+ oeisInformation = _getOEISofficial(pathFilenameCache, url)
195
+
196
+ if not oeisInformation:
197
+ return "Not found", -1
198
+
199
+ description_parts = []
200
+ offset = None
201
+ for line in oeisInformation.splitlines():
202
+ if line.startswith('%N'):
203
+ parts = line.split()
204
+ if parts[1] == oeisID:
205
+ desc_part = ' '.join(parts[2:])
206
+ description_parts.append(desc_part)
207
+ elif line.startswith('%O'):
208
+ parts = line.split()
209
+ if parts[1] == oeisID:
210
+ offset_str = parts[2].split(',')[0]
211
+ offset = int(offset_str)
212
+ if not description_parts:
213
+ warnings.warn(f"No description found for {oeisID}")
214
+ description_parts.append("No description found")
215
+ if offset is None:
216
+ warnings.warn(f"No offset found for {oeisID}")
217
+ offset = -1
218
+ description = ' '.join(description_parts)
219
+ return description, offset
220
220
 
221
221
  def makeSettingsOEIS() -> Dict[str, SettingsOEIS]:
222
- settingsTarget = {}
223
- for oeisID in oeisIDsImplemented:
224
- valuesKnownSherpa = _getOEISidValues(oeisID)
225
- descriptionSherpa, offsetSherpa = _getOEISidInformation(oeisID)
226
- settingsTarget[oeisID] = SettingsOEIS(
227
- description=descriptionSherpa,
228
- offset=offsetSherpa,
229
- getMapShape=settingsOEIShardcodedValues[oeisID]['getMapShape'],
230
- valuesBenchmark=settingsOEIShardcodedValues[oeisID]['valuesBenchmark'],
231
- valuesTestParallelization=settingsOEIShardcodedValues[oeisID]['valuesTestParallelization'],
232
- valuesTestValidation=settingsOEIShardcodedValues[oeisID]['valuesTestValidation'],
233
- valuesKnown=valuesKnownSherpa,
234
- valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1
235
- )
236
- return settingsTarget
222
+ settingsTarget = {}
223
+ for oeisID in oeisIDsImplemented:
224
+ valuesKnownSherpa = _getOEISidValues(oeisID)
225
+ descriptionSherpa, offsetSherpa = _getOEISidInformation(oeisID)
226
+ settingsTarget[oeisID] = SettingsOEIS(
227
+ description=descriptionSherpa,
228
+ offset=offsetSherpa,
229
+ getMapShape=settingsOEIShardcodedValues[oeisID]['getMapShape'],
230
+ valuesBenchmark=settingsOEIShardcodedValues[oeisID]['valuesBenchmark'],
231
+ valuesTestParallelization=settingsOEIShardcodedValues[oeisID]['valuesTestParallelization'],
232
+ valuesTestValidation=settingsOEIShardcodedValues[oeisID]['valuesTestValidation'] + list(range(offsetSherpa, 2)),
233
+ valuesKnown=valuesKnownSherpa,
234
+ valueUnknown=max(valuesKnownSherpa.keys(), default=0) + 1
235
+ )
236
+ return settingsTarget
237
237
 
238
238
  settingsOEIS: Dict[str, SettingsOEIS] = makeSettingsOEIS()
239
239
  """All values and settings for `oeisIDsImplemented`."""
@@ -242,98 +242,98 @@ settingsOEIS: Dict[str, SettingsOEIS] = makeSettingsOEIS()
242
242
  Section: private functions"""
243
243
 
244
244
  def _formatHelpText() -> str:
245
- """Format standardized help text for both CLI and interactive use."""
246
- exampleOEISid = oeisIDsImplemented[0]
247
- exampleN = settingsOEIS[exampleOEISid]['valuesTestValidation'][-1]
248
-
249
- return (
250
- "\nAvailable OEIS sequences:\n"
251
- f"{_formatOEISsequenceInfo()}\n"
252
- "\nUsage examples:\n"
253
- " Command line:\n"
254
- f" OEIS_for_n {exampleOEISid} {exampleN}\n"
255
- " Python:\n"
256
- " from mapFolding import oeisIDfor_n\n"
257
- f" foldsTotal = oeisIDfor_n('{exampleOEISid}', {exampleN})"
258
- )
245
+ """Format standardized help text for both CLI and interactive use."""
246
+ exampleOEISid = oeisIDsImplemented[0]
247
+ exampleN = settingsOEIS[exampleOEISid]['valuesTestValidation'][-1]
248
+
249
+ return (
250
+ "\nAvailable OEIS sequences:\n"
251
+ f"{_formatOEISsequenceInfo()}\n"
252
+ "\nUsage examples:\n"
253
+ " Command line:\n"
254
+ f" OEIS_for_n {exampleOEISid} {exampleN}\n"
255
+ " Python:\n"
256
+ " from mapFolding import oeisIDfor_n\n"
257
+ f" foldsTotal = oeisIDfor_n('{exampleOEISid}', {exampleN})"
258
+ )
259
259
 
260
260
  def _formatOEISsequenceInfo() -> str:
261
- """Format information about available OEIS sequences for display or error messages."""
262
- return "\n".join(
263
- f" {oeisID}: {settingsOEIS[oeisID]['description']}"
264
- for oeisID in oeisIDsImplemented
265
- )
261
+ """Format information about available OEIS sequences for display or error messages."""
262
+ return "\n".join(
263
+ f" {oeisID}: {settingsOEIS[oeisID]['description']}"
264
+ for oeisID in oeisIDsImplemented
265
+ )
266
266
 
267
267
  """
268
268
  Section: public functions"""
269
269
 
270
270
  def oeisIDfor_n(oeisID: str, n: int) -> int:
271
- """
272
- Calculate a(n) of a sequence from "The On-Line Encyclopedia of Integer Sequences" (OEIS).
271
+ """
272
+ Calculate a(n) of a sequence from "The On-Line Encyclopedia of Integer Sequences" (OEIS).
273
273
 
274
- Parameters:
275
- oeisID: The ID of the OEIS sequence.
276
- n: A non-negative integer for which to calculate the sequence value.
274
+ Parameters:
275
+ oeisID: The ID of the OEIS sequence.
276
+ n: A non-negative integer for which to calculate the sequence value.
277
277
 
278
- Returns:
279
- sequenceValue: a(n) of the OEIS sequence.
278
+ Returns:
279
+ sequenceValue: a(n) of the OEIS sequence.
280
280
 
281
- Raises:
282
- ValueError: If n is negative.
283
- KeyError: If the OEIS sequence ID is not directly implemented.
284
- """
285
- oeisID = _validateOEISid(oeisID)
281
+ Raises:
282
+ ValueError: If n is negative.
283
+ KeyError: If the OEIS sequence ID is not directly implemented.
284
+ """
285
+ oeisID = _validateOEISid(oeisID)
286
286
 
287
- if not isinstance(n, int) or n < 0:
288
- raise ValueError("`n` must be non-negative integer.")
287
+ if not isinstance(n, int) or n < 0:
288
+ raise ValueError("`n` must be non-negative integer.")
289
289
 
290
- listDimensions = settingsOEIS[oeisID]['getMapShape'](n)
290
+ listDimensions = settingsOEIS[oeisID]['getMapShape'](n)
291
291
 
292
- if n <= 1 or len(listDimensions) < 2:
293
- offset = settingsOEIS[oeisID]['offset']
294
- if n < offset:
295
- raise ArithmeticError(f"OEIS sequence {oeisID} is not defined at n={n}.")
296
- foldsTotal = settingsOEIS[oeisID]['valuesKnown'][n]
297
- return foldsTotal
292
+ if n <= 1 or len(listDimensions) < 2:
293
+ offset = settingsOEIS[oeisID]['offset']
294
+ if n < offset:
295
+ raise ArithmeticError(f"OEIS sequence {oeisID} is not defined at n={n}.")
296
+ foldsTotal = settingsOEIS[oeisID]['valuesKnown'][n]
297
+ return foldsTotal
298
298
 
299
- return countFolds(listDimensions)
299
+ return countFolds(listDimensions)
300
300
 
301
301
  def OEIS_for_n() -> None:
302
- """Command-line interface for oeisIDfor_n."""
303
- parserCLI = argparse.ArgumentParser(
304
- description="Calculate a(n) for an OEIS sequence.",
305
- epilog=_formatHelpText(),
306
- formatter_class=argparse.RawDescriptionHelpFormatter
307
- )
308
- parserCLI.add_argument('oeisID', help="OEIS sequence identifier")
309
- parserCLI.add_argument('n', type=int, help="Calculate a(n) for this n")
302
+ """Command-line interface for oeisIDfor_n."""
303
+ parserCLI = argparse.ArgumentParser(
304
+ description="Calculate a(n) for an OEIS sequence.",
305
+ epilog=_formatHelpText(),
306
+ formatter_class=argparse.RawDescriptionHelpFormatter
307
+ )
308
+ parserCLI.add_argument('oeisID', help="OEIS sequence identifier")
309
+ parserCLI.add_argument('n', type=int, help="Calculate a(n) for this n")
310
310
 
311
- argumentsCLI = parserCLI.parse_args()
311
+ argumentsCLI = parserCLI.parse_args()
312
312
 
313
- timeStart = time.perf_counter()
313
+ timeStart = time.perf_counter()
314
314
 
315
- try:
316
- print(oeisIDfor_n(argumentsCLI.oeisID, argumentsCLI.n), "distinct folding patterns.")
317
- except (KeyError, ValueError, ArithmeticError) as ERRORmessage:
318
- print(f"Error: {ERRORmessage}", file=sys.stderr)
319
- sys.exit(1)
315
+ try:
316
+ print(oeisIDfor_n(argumentsCLI.oeisID, argumentsCLI.n), "distinct folding patterns.")
317
+ except (KeyError, ValueError, ArithmeticError) as ERRORmessage:
318
+ print(f"Error: {ERRORmessage}", file=sys.stderr)
319
+ sys.exit(1)
320
320
 
321
- timeElapsed = time.perf_counter() - timeStart
322
- print(f"Time elapsed: {timeElapsed:.3f} seconds")
321
+ timeElapsed = time.perf_counter() - timeStart
322
+ print(f"Time elapsed: {timeElapsed:.3f} seconds")
323
323
 
324
324
  def clearOEIScache() -> None:
325
- """Delete all cached OEIS sequence files."""
326
- if not _pathCache.exists():
327
- print(f"Cache directory, {_pathCache}, not found - nothing to clear.")
328
- return
329
- for oeisID in settingsOEIS:
330
- ( _pathCache / f"{oeisID}.txt" ).unlink(missing_ok=True)
331
- ( _pathCache / _getFilenameOEISbFile(oeisID) ).unlink(missing_ok=True)
332
- print(f"Cache cleared from {_pathCache}")
325
+ """Delete all cached OEIS sequence files."""
326
+ if not _pathCache.exists():
327
+ print(f"Cache directory, {_pathCache}, not found - nothing to clear.")
328
+ return
329
+ for oeisID in settingsOEIS:
330
+ ( _pathCache / f"{oeisID}.txt" ).unlink(missing_ok=True)
331
+ ( _pathCache / _getFilenameOEISbFile(oeisID) ).unlink(missing_ok=True)
332
+ print(f"Cache cleared from {_pathCache}")
333
333
 
334
334
  def getOEISids() -> None:
335
- """Print all available OEIS sequence IDs that are directly implemented."""
336
- print(_formatHelpText())
335
+ """Print all available OEIS sequence IDs that are directly implemented."""
336
+ print(_formatHelpText())
337
337
 
338
338
  if __name__ == "__main__":
339
- getOEISids()
339
+ getOEISids()