Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,54 @@
from itertools import islice
class INW():
"""
Intersecting Number Wheels
represented as a dict mapping
name to tuple of values.
"""
def __init__(self, **wheels):
self._wheels = wheels
self.isect = {name: self._wstate(name, wheel)
for name, wheel in wheels.items()}
def _wstate(self, name, wheel):
"Wheel state holder"
assert all(val in self._wheels for val in wheel if type(val) == str), \
f"ERROR: Interconnected wheel not found in {name}: {wheel}"
pos = 0
ln = len(wheel)
while True:
nxt, pos = wheel[pos % ln], pos + 1
yield next(self.isect[nxt]) if type(nxt) == str else nxt
def __iter__(self):
base_wheel_name = next(self.isect.__iter__())
yield from self.isect[base_wheel_name]
def __repr__(self):
return f"{self.__class__.__name__}({self._wheels})"
def __str__(self):
txt = "Intersecting Number Wheel group:"
for name, wheel in self._wheels.items():
txt += f"\n {name+':':4}" + ' '.join(str(v) for v in wheel)
return txt
def first(iter, n):
"Pretty print first few terms"
return ' '.join(f"{nxt}" for nxt in islice(iter, n))
if __name__ == '__main__':
for group in[
{'A': (1, 2, 3)},
{'A': (1, 'B', 2),
'B': (3, 4)},
{'A': (1, 'D', 'D'),
'D': (6, 7, 8)},
{'A': (1, 'B', 'C'),
'B': (3, 4),
'C': (5, 'B')}, # 135143145...
]:
w = INW(**group)
print(f"{w}\n Generates:\n {first(w, 20)} ...\n")

View file

@ -0,0 +1,21 @@
def nextfrom(w, name):
while True:
nxt, w[name] = w[name][0], w[name][1:] + w[name][:1]
if '0' <= nxt[0] <= '9':
return nxt
name = nxt
if __name__ == '__main__':
for group in '''
A: 1 2 3
A: 1 B 2; B: 3 4
A: 1 D D; D: 6 7 8
A: 1 B C; B: 3 4; C: 5 B'''.strip().split('\n'):
print(f"Intersecting Number Wheel group:\n {group}")
wheel, first = {}, None
for w in group.strip().split(';'):
name, *values = w.strip().split()
wheel[name[:-1]] = values
first = name[:-1] if first is None else first
gen = ' '.join(nextfrom(wheel, first) for i in range(20))
print(f" Generates:\n {gen} ...\n")

View file

@ -0,0 +1,13 @@
def nextfromr(w, name):
nxt, w[name] = w[name][0], w[name][1:] + w[name][:1]
return nxt if '0' <= nxt[0] <= '9' else nextfromr(w, nxt)
if __name__ == '__main__':
for group in [{'A': '123'},
{'A': '1B2', 'B': '34'},
{'A': '1DD', 'D': '678'},
{'A': '1BC', 'B': '34', 'C': '5B'},]:
print(f"Intersecting Number Wheel group:\n {group}")
first = next(group.__iter__())
gen = ' '.join(nextfromr(group, first) for i in range(20))
print(f" Generates:\n {gen} ...\n")

View file

@ -0,0 +1,107 @@
'''Intersecting number wheels'''
from itertools import cycle, islice
from functools import reduce
# clockWorkTick :: Dict -> (Dict, Char)
def clockWorkTick(wheelMap):
'''The new state of the wheels, tupled with a
digit found by recursive descent from a single
click of the first wheel.'''
def click(wheels):
def go(wheelName):
wheel = wheels.get(wheelName, ['?'])
v = wheel[0]
return (Tuple if v.isdigit() or '?' == v else click)(
insertDict(wheelName)(leftRotate(wheel))(wheels)
)(v)
return go
return click(wheelMap)('A')
# leftRotate :: [a] -> String
def leftRotate(xs):
''' A string shifted cyclically towards
the left by one position.
'''
return ''.join(islice(cycle(xs), 1, 1 + len(xs)))
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''First twenty values from each set of test wheels.'''
wheelMaps = [dict(kvs) for kvs in [
[('A', "123")],
[('A', "1B2"), ('B', "34")],
[('A', "1DD"), ('D', "678")],
[('A', "1BC"), ('B', "34"), ('C', "5B")]
]]
print('New state of wheel sets, after 20 clicks of each:\n')
for wheels, series in [
mapAccumL(compose(const)(clockWorkTick))(
dct
)(' ' * 20) for dct in wheelMaps
]:
print((wheels, ''.join(series)))
print('\nInital states:')
for x in wheelMaps:
print(x)
# ----------------------- GENERIC ------------------------
# Tuple (,) :: a -> b -> (a, b)
def Tuple(x):
'''Constructor for a pair of values,
possibly of two different types.
'''
return lambda y: (
x + (y,)
) if isinstance(x, tuple) else (x, y)
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
# const :: a -> b -> a
def const(k):
'''The latter of two arguments,
with the first discarded.
'''
return lambda _: k
# insertDict :: String -> a -> Dict -> Dict
def insertDict(k):
'''A new dictionary updated with a (k, v) pair.'''
def go(v, dct):
return dict(dct, **{k: v})
return lambda v: lambda dct: go(v, dct)
# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumL(f):
'''A tuple of an accumulation and a map
with accumulation from left to right.
'''
def nxt(a, x):
tpl = f(a[0])(x)
return tpl[0], a[1] + [tpl[1]]
def go(acc):
def g(xs):
return reduce(nxt, xs, (acc, []))
return g
return go
# MAIN ---
if __name__ == '__main__':
main()