:- use_module(library(pio)). :- use_module(library(dcg/basics)). :- initialization(main, main). main([FileName|_]) :- input(FileName, Circuit), run1000(Circuit, Answer), write(Answer), nl. % part1 run1000(Circuit, Answer) :- length(Range, 1000), foldl( {Circuit}/[_, In-Lin-Hin, Out-Lout-Hout]>>( run([button-l-broadcaster], In, Out, L-H), Lout is L+Lin, Hout is H+Hin), Range, Circuit-0-0, _-Lx-Hx), Answer is Lx*Hx. % code to run one circuit run([], Circuit, Circuit, 0-0). run([Src-Level-Target|Pulses], CircuitIn, CircuitOut, Ls-Hs) :- ( member(Type-Target-State-Dests, CircuitIn) -> /*write([Src, Level, Target]), write(" -> "), write([Type, Target, State, Dests]), write(" = "),*/ call(Type, Src, Level, State, NewState, Out), send(Target, Out, Dests, AdditionalPulses), % write(NewState-AdditionalPulses), nl, select(Type-Target-State-Dests, CircuitIn, Type-Target-NewState-Dests, Circuit1), append(Pulses, AdditionalPulses, NewPulses), run(NewPulses, Circuit1, CircuitOut, NextLs-NextHs) ; run(Pulses, CircuitIn, CircuitOut, NextLs-NextHs) ), call(Level, NextLs-NextHs, Ls-Hs). l(L1s-H1s, L2s-H1s) :- L2s is L1s + 1. h(L1s-H1s, L1s-H2s) :- H2s is H1s + 1. broadcaster(_, l, x, x, l). ff(_, h, State, State, none). ff(_, l, 0, 1, h). ff(_, l, 1, 0, l). nand(Src, Level, State, NewState, OutLevel) :- select(Src-_, State, Src-Level, NewState), (maplist([_-h]>>(true), NewState) -> OutLevel = l; OutLevel = h). send(_, none, _, []). send(From, Level, Dests, Pulses) :- \+ Level = none, maplist({Level}/[Dest, From-Level-Dest]>>(true), Dests, Pulses). % input initialization prefill_nands([], Circuit, Circuit). prefill_nands([_-Src-_-Dests|Nodes], CircuitIn, CircuitOut) :- convlist( {CircuitIn}/[Dest, Dest]>>(member(nand-Dest-_-_, CircuitIn)), Dests, NandDests), foldl(fill_one_nand(Src), NandDests, CircuitIn, Circuit1), prefill_nands(Nodes, Circuit1, CircuitOut). fill_one_nand(Src, Nand, CIn, COut) :- select(nand-Nand-State-Dests, CIn, nand-Nand-[Src-l|State]-Dests, COut). % input parsing stuff below input(FileName, Circuit) :- phrase_from_file(modules(EmptyCircuit), FileName), prefill_nands(EmptyCircuit, EmptyCircuit, Circuit). modules([]) --> eos, !. modules([Module|Modules]) --> module(Module), "\n", modules(Modules). module(broadcaster-broadcaster-x-Dests) --> "broadcaster -> ", dests(Dests). module(ff-Name-0-Dests) --> "%", node(Name), " -> ", dests(Dests). module(nand-Name-[]-Dests) --> "&", node(Name), " -> ", dests(Dests). dests([Dest]) --> node(Dest). dests([Dest|Dests]) --> node(Dest), ", ", dests(Dests). node(Name) --> string_without(", \n", NameStr), {atom_codes(Name, NameStr)}.