:- use_module(library(pio)). :- use_module(library(dcg/basics)). :- use_module(library(clpfd)). :- initialization(main, main). main([FileName|_]) :- input(FileName, Actions), perform_all(Actions, Boxes), findall(Power, power_of_some_lens(Boxes, Power), Powers), sum_list(Powers, Answer), writef('Answer=%t\n', [Answer]). power_of_some_lens(Boxes, Power) :- nth1(BoxI, Boxes, _-Box), nth1(LensI, Box, _-Focal), Power is BoxI * LensI * Focal. perform_all(Actions, FinalBoxes) :- length(EmptyBoxes, 256), foldl([N-[], N, NextN]>>(NextN is N + 1), EmptyBoxes, 0, _), foldl(perform, Actions, EmptyBoxes, FinalBoxes). perform(BoxN-Action-Label, Before, After) :- nth0(BoxN, Before, BoxN-Box), call(Action, Label, Box, NewBox), select(BoxN-Box, Before, BoxN-NewBox, After). remove(_, [], []). remove(Label, [Label-_|Box], Box) :- !. remove(Label, [Lens|Box], [Lens|NewBox]) :- remove(Label, Box, NewBox). add(Focal, Label, Box, NewBox) :- select(Label-_, Box, Label-Focal, NewBox), !. add(Focal, Label, Box, NewBox) :- append(Box, [Label-Focal], NewBox). % Input stuff. [0-(add-1)-"rn", 3-remove-"cm", ...] input(Name, Actions) :- phrase_from_file(insts(Actions), Name). insts([]) --> (eos; "\n"), !. insts([Box-Action-LabelS|Items]) --> item(Label-Action), insts(Items), {reverse(Label, Rev), hash(Rev, Box), string_codes(LabelS, Label)}. item([]-remove) --> "-", (","; "\n"; eos), !. item([]-add(N)) --> "=", number(N), (","; "\n"; eos), !. item([C|Chars]-X) --> [C], item(Chars-X). hash([], 0). hash([C|Str], Hash) :- hash(Str, Prev), Hash is (Prev + C)*17 mod 256.