simplified chains.py
This commit is contained in:
82
chains.py
Normal file
82
chains.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""Enumerate flattened redstone delay-chains for a given total delay."""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
class Comp(NamedTuple):
|
||||
delay: int
|
||||
priority: int
|
||||
blocks: tuple
|
||||
|
||||
|
||||
# Append custom subcomponents here, e.g. Comp(6, -1, ("-", "R2", "C")).
|
||||
COMPONENTS = [
|
||||
Comp(8, -3, ("R4",)),
|
||||
Comp(6, -3, ("R3",)),
|
||||
Comp(4, -3, ("R2",)),
|
||||
Comp(2, -3, ("R1",)),
|
||||
Comp(8, -1, ("-", "R4")),
|
||||
Comp(6, -1, ("-", "R3")),
|
||||
Comp(4, -1, ("-", "R2")),
|
||||
Comp(2, -1, ("C",)),
|
||||
Comp(2, -1, ("-", "R1")),
|
||||
Comp(2, 0, ("-", "C")),
|
||||
]
|
||||
|
||||
assert all(c.blocks for c in COMPONENTS), "components must have >= 1 block"
|
||||
_ORDERED = sorted(COMPONENTS, key=lambda c: (c.priority, -c.delay))
|
||||
|
||||
|
||||
def _canon(comps):
|
||||
seen = {}
|
||||
for c in comps:
|
||||
seen.setdefault((c.priority, c.delay), c)
|
||||
return list(seen.values())
|
||||
|
||||
|
||||
HEAD = _canon([c for c in _ORDERED if c.blocks[0] == "-"])
|
||||
BODY = _canon(_ORDERED)
|
||||
|
||||
|
||||
def chains(total: int):
|
||||
for c in HEAD:
|
||||
if c.delay > total:
|
||||
continue
|
||||
if total == c.delay:
|
||||
yield c.blocks
|
||||
else:
|
||||
for rest in _body(total - c.delay):
|
||||
yield c.blocks + rest
|
||||
|
||||
|
||||
def _body(remaining: int):
|
||||
for c in BODY:
|
||||
if c.delay > remaining:
|
||||
continue
|
||||
if remaining == c.delay:
|
||||
yield c.blocks
|
||||
else:
|
||||
for rest in _body(remaining - c.delay):
|
||||
yield c.blocks + rest
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description=__doc__)
|
||||
ap.add_argument("total", type=int, help="total delay to enumerate")
|
||||
ap.add_argument("count", nargs="*", type=int, help="total element count")
|
||||
args = ap.parse_args()
|
||||
|
||||
tileset = chains(args.total)
|
||||
if args.count:
|
||||
tileset = (chain for chain in tileset if len(chain) in args.count)
|
||||
tileset = list(tileset)
|
||||
|
||||
for chain in tileset:
|
||||
print(*chain)
|
||||
print(len(tileset), "chains", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user