55 lines
1.7 KiB
Perl
55 lines
1.7 KiB
Perl
|
:- 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).
|