65 lines
1.6 KiB
Nim
65 lines
1.6 KiB
Nim
import strutils, tables
|
|
|
|
type
|
|
|
|
ElemKind = enum eValue, eWheel
|
|
|
|
Elem = object
|
|
case kind: ElemKind
|
|
of eValue:
|
|
value: Natural
|
|
of eWheel:
|
|
name: char
|
|
|
|
Wheel = ref object
|
|
elems: seq[Elem]
|
|
index: Natural
|
|
|
|
Wheels = Table[char, Wheel]
|
|
|
|
WheelDescription = tuple[name: char; elems: string]
|
|
|
|
|
|
func initWheels(wheels: openArray[WheelDescription]): Wheels =
|
|
## Initialize a table of wheels from an array of wheel descriptions.
|
|
|
|
for (name, elems) in wheels:
|
|
let wheel = new(Wheel)
|
|
for e in elems.splitWhitespace():
|
|
if e[0].isUpperAscii():
|
|
wheel.elems.add Elem(kind: eWheel, name: e[0])
|
|
else:
|
|
wheel.elems.add Elem(kind: eValue, value: e.parseInt())
|
|
result[name] = wheel
|
|
|
|
|
|
func next(wheels: Wheels; name: char): Natural =
|
|
## Return the next element from a wheel.
|
|
|
|
let wheel = wheels[name]
|
|
let elem = wheel.elems[wheel.index]
|
|
wheel.index = (wheel.index + 1) mod wheel.elems.len
|
|
result = case elem.kind
|
|
of eValue: elem.value
|
|
of eWheel: wheels.next(elem.name)
|
|
|
|
|
|
when isMainModule:
|
|
|
|
proc generate(wheelList: openArray[WheelDescription]; count: Positive) =
|
|
## Create the wheels from their description, then display
|
|
## the first "count" values generated by wheel 'A'.
|
|
|
|
let wheels = wheelList.initWheels()
|
|
for (name, elems) in wheelList:
|
|
echo name, ": ", elems
|
|
echo "generates:"
|
|
for _ in 1..count:
|
|
stdout.write ' ', wheels.next('A')
|
|
echo '\n'
|
|
|
|
|
|
{'A': "1 2 3"}.generate(20)
|
|
{'A': "1 B 2", 'B': "3 4"}.generate(20)
|
|
{'A': "1 D D", 'D': "6 7 8"}.generate(20)
|
|
{'A': "1 B C", 'B': "3 4", 'C': "5 B"}.generate(20)
|