RosettaCodeData/Task/Intersecting-number-wheels/Python/intersecting-number-wheels-...

55 lines
1.6 KiB
Python

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")