record rule [ cat : int; rel : byte; num : int; dest : bytes; ] fn find_recursive(rules : treemap(bytes, list(rule)), st : array(int, [4]), en : array(int, [4]), rl : list(rule)) : int [ var sum := 0; repeat: var r := rl[0]; if r.rel = 0 then goto match; var num := r.num; if r.rel = '<' then [ if num < st[r.cat] then goto match; if num >= en[r.cat] then goto no_match; var en2 := en; var st2 := st; en2[r.cat] := num - 1; st2[r.cat] := num; sum += find_recursive(rules, st2, en, rl[1 .. ]); en := en2; goto match; ] else if r.rel = '>' then [ if num > en[r.cat] then goto match; if num <= st[r.cat] then goto no_match; var en2 := en; var st2 := st; en2[r.cat] := num; st2[r.cat] := num + 1; sum += find_recursive(rules, st, en2, rl[1 .. ]); st := st2; goto match; ] else abort; no_match: rl := rl[1 .. ]; goto repeat; match: if r.dest = "A" then goto accept; if r.dest = "R" then goto reject; rl := treemap_search(rules, r.dest).j; goto repeat; accept: var mult := 1; for i := 0 to 4 do mult *= en[i] + 1 - st[i]; return sum + mult; reject: return sum; ] fn main [ var cat2ch := "xmas"; var lines := list_break_to_lines(read_lazy(h[0])); var xlines := list_break(lines, ""); var rules := treemap_init(bytes, list(rule)); for l in xlines[0] do [ var s := list_search(l, '{'); var name := l[ .. s]; var rs := list_break(l[s + 1 .. len(l) - 1], ','); var r := empty(rule); for q in rs do [ var c := list_search(q, ':'); if c = -1 then [ r +<= rule.[ cat : -1, rel : 0, num : 0, dest : q ]; ] else [ r +<= rule.[ cat : list_search(cat2ch, q[0]), rel : q[1], num : ston(q[2 .. c]), dest : q[c + 1 .. ] ]; ] ] rules := treemap_insert(rules, name, r); ] var st := list_to_array([4], [ 1, 1, 1, 1 ]); var en := list_to_array([4], [ 4000, 4000, 4000, 4000 ]); var sum := find_recursive(rules, st, en, treemap_search(rules, "in").j); write(h[1], ntos(sum) + nl); ]