:- use_module(library(pio)). :- use_module(library(dcg/basics)). :- initialization(main, main). main([FileName|_]) :- input(FileName, Workflows, Parts), concurrent_maplist(wf(Workflows, in), Parts, Scores), sum_list(Scores, Score), write(Score), nl. wf(_, accept, [x-X, m-M, a-A, s-S], Score) :- Score is X + M + A + S, !. wf(_, reject, _Part, 0) :- !. wf(Workflows, WorkflowName, Part, Score) :- member(WorkflowName-Rules, Workflows), rule(Workflows, Rules, Part, Score). rule(Workflows, [EndRule], Part, Score) :- wf(Workflows, EndRule, Part, Score). rule(Workflows, [Attr-Cond-N-Dest|Rules], Part, Score) :- ( satisfy(Attr-Cond-N, Part) -> wf(Workflows, Dest, Part, Score) ; rule(Workflows, Rules, Part, Score) ). satisfy(Attr-Cond-N, Part) :- member(Attr-M, Part), call(Cond, M, N). % input parsing stuff below input(FileName, Workflows, Parts) :- phrase_from_file((workflows(Workflows), parts(Parts)), FileName). workflows([]) --> "\n", !. workflows([Name-Rules|Ws]) --> string_without("{", NameStr), "{", rules(Rules), "}\n", workflows(Ws), {atom_codes(Name, NameStr)}. rules([End]) --> dest(End). rules([Rule|Rules]) --> rule(Rule), ",", rules(Rules). rule(Attr-Cond-N-Dest) --> attr(Attr), cond(Cond), number(N), ":", dest(Dest). attr(x) --> "x". attr(m) --> "m". attr(a) --> "a". attr(s) --> "s". cond('>') --> ">". cond('<') --> "<". dest(reject) --> "R", !. dest(accept) --> "A", !. dest(Dest) --> endrule(Dest). endrule(Rule) --> string_without(",}", RuleStr), {atom_codes(Rule, RuleStr)}. parts([]) --> eos, !. parts([[x-X, m-M, a-A, s-S]|Parts]) --> "{x=", number(X), ",m=", number(M), ",a=", number(A), ",s=", number(S), "}\n", parts(Parts).