const array_size := ipower(27, 3); fn array_index(s : bytes) : int [ if s = "broadcaster" then return 0; if s = "output" then s := "out"; var idx := 0; for q in s do idx := idx * 27 + (q - 'a' + 1); return idx; ] option typ [ nothing; bcst; ff : bool; conj : list(tuple2(int, bool)); ] record module [ t : typ; result : list(int); ] fn main [ var lines := list_break_to_lines(read_lazy(h[0])); var modules := array_fill(module.[ t : typ.nothing, result : empty(int) ], [array_size]); for line in lines do [ line := list_replace_substring(line, " ", ""); line := list_replace_substring(line, "->", "-"); var l := list_break(line, '-'); var rl := list_break(l[1], ','); var result := map(rl, array_index); var nm := l[0]; var t : typ; if nm[0] = '%' then [ t := typ.ff.(false); nm := nm[1 .. ]; ] else if nm[0] = '&' then [ t := typ.conj.(empty(tuple2(int, bool))); nm := nm[1 .. ]; ] else [ t := typ.bcst; ] var mod := module.[ t : t, result : result ]; modules[array_index(nm)] := mod; ] for i := 0 to array_size do [ for j in modules[i].result do [ if modules[j].t is conj then [ modules[j].t.conj +<= mktuple2(i, false); ] ] ] var low_pulses := 0; var high_pulses := 0; for i := 0 to 1000 do [ var pulse_queue := [ mktuple3(false, 0, array_index("broadcaster")) ]; while len_greater_than(pulse_queue, 0) do [ var p := pulse_queue[0]; pulse_queue := pulse_queue[1 .. ]; if not p.v1 then low_pulses += 1; else high_pulses += 1; var midx := p.v3; var m := modules[p.v3]; var target_pulse : bool; if m.t is bcst then [ target_pulse := p.v1; goto send; ] if m.t is ff then [ if p.v1 then continue; modules[midx].t.ff := not modules[midx].t.ff; target_pulse := modules[midx].t.ff; goto send; ] if m.t is conj then [ for j := 0 to len(m.t.conj) do [ if m.t.conj[j].v1 = p.v2 then [ modules[midx].t.conj[j].v2 := p.v1; goto found; ] ] abort; found: target_pulse := false; for j := 0 to len(m.t.conj) do [ if not modules[midx].t.conj[j].v2 then [ target_pulse := true; break; ] ] goto send; ] continue; send: for j := 0 to len(m.result) do [ pulse_queue +<= mktuple3(target_pulse, midx, m.result[j]); ] ] ] write(h[1], ntos(low_pulses * high_pulses) + nl); ]