···1+import "trilogy:debug" use dbg
2+import "trilogy:io" use readall, println
3+import "trilogy:parsec" use parse, apply, per_line, choice, char, string, integer, followed_by, eof
4+import "trilogy:array" use fold
5+6+proc argument!() {
7+ apply <| choice [
8+ char 'w',
9+ char 'x',
10+ char 'y',
11+ char 'z',
12+ integer,
13+ ]
14+}
15+16+proc instruction!() {
17+ let op_code = apply <| choice [
18+ string "inp",
19+ string "add",
20+ string "mul",
21+ string "div",
22+ string "mod",
23+ string "eql",
24+ ]
25+ apply <| char ' '
26+ match op_code {
27+ case "inp" then 'inp(apply argument)
28+ case "add" then 'add(apply (followed_by (char ' ') argument):apply argument)
29+ case "mul" then 'mul(apply (followed_by (char ' ') argument):apply argument)
30+ case "div" then 'div(apply (followed_by (char ' ') argument):apply argument)
31+ case "mod" then 'mod(apply (followed_by (char ' ') argument):apply argument)
32+ case "eql" then 'eql(apply (followed_by (char ' ') argument):apply argument)
33+ }
34+}
35+36+proc countdown!(cb) {
37+ with cb!() {
38+ when 'inp then {
39+ for option in [9, 8, 7, 6, 5, 4, 3, 2, 1] {
40+ match resume option {
41+ case 'some(val) then cancel 'some("${option}${val}")
42+ }
43+ }
44+ cancel 'none
45+ }
46+ }
47+}
48+49+func set 'w' w [_, x, y, z] = [w, x, y, z]
50+func set 'x' x [w, _, y, z] = [w, x, y, z]
51+func set 'y' y [w, x, _, z] = [w, x, y, z]
52+func set 'z' z [w, x, y, _] = [w, x, y, z]
53+54+func get val and typeof 'number _ = val
55+func get 'w' [w, _, _, _] = w
56+func get 'x' [_, x, _, _] = x
57+func get 'y' [_, _, y, _] = y
58+func get 'z' [_, _, _, z] = z
59+60+func apply_instruction _ 'none = 'none
61+func apply_instruction 'inp(var) 'some(state) = 'some(set var (yield 'inp) state)
62+func apply_instruction 'add(var:rhs) 'some(state) = 'some(set var (get var state + get rhs state) state)
63+func apply_instruction 'mul(var:rhs) 'some(state) = 'some(set var (get var state * get rhs state) state)
64+func apply_instruction 'div(var:rhs) 'some(state) = 'some(set var (get var state // get rhs state) state)
65+func apply_instruction 'mod(var:rhs) 'some(state) = 'some(set var (get var state % get rhs state) state)
66+func apply_instruction 'eql(var:rhs) 'some(state) = 'some(set var (if get var state == get rhs state then 1 else 0) state)
67+68+func evaluate program state = fold (fn i s. apply_instruction i s) 'some(state) program
69+70+func maybe option cb = match option {
71+ case 'some(val) then cb val
72+ else 'none
73+}
74+75+proc main!() {
76+ let program = parse (followed_by eof <| per_line instruction) readall!()
77+ let 'some(result) = {
78+ using countdown
79+ do(state) using maybe (evaluate program [0, 0, 0, 0])
80+ if get 'z' state == 0 then 'some("") else 'none
81+ }
82+ println!(result)
83+}