81 lines
1.9 KiB
Prolog
81 lines
1.9 KiB
Prolog
char(X, L, C0, L, C) -->
|
|
[X0], {X0 \= 0'\n, char_code(X, X0), C is C0 + 1}, !.
|
|
|
|
digit(D, L0, C0, L, C) --> char(D, L0, C0, L, C), {char_type(D, digit)}.
|
|
|
|
digits([D|Ds], L0, C0, L, C) -->
|
|
digit(D, L0, C0, L1, C1),
|
|
digits0(Ds, L1, C1, L, C).
|
|
digits0(Ds, L0, C0, L, C) --> digits(Ds, L0, C0, L, C).
|
|
digits0([], L, C, L, C) --> [].
|
|
|
|
newline(L0, _, L, 0) --> "\n", {L is L0 + 1}.
|
|
|
|
num(n(N, L-C0-C1), L, C0, L, C) -->
|
|
digits(Ds, L, C0, L, C), !,
|
|
{number_chars(N, Ds), C1 is C - 1}.
|
|
|
|
dot(L0, C0, L, C) --> char('.', L0, C0, L, C).
|
|
|
|
sym(s(X, L-C0), L, C0, L, C) -->
|
|
char(X, L, C0, L, C),
|
|
{\+ char_type(X, digit), X \= '.'}.
|
|
|
|
thing(X, L0, C0, L, C) --> num(X, L0, C0, L, C).
|
|
thing(X, L0, C0, L, C) --> sym(X, L0, C0, L, C).
|
|
|
|
nonthing(L0, C0, L, C) --> dot(L0, C0, L, C).
|
|
nonthing(L0, C0, L, C) --> newline(L0, C0, L, C).
|
|
|
|
input([], L, C, L, C) --> [].
|
|
|
|
input([I|Is], L0, C0, L, C) -->
|
|
thing(I, L0, C0, L1, C1), !,
|
|
input(Is, L1, C1, L, C).
|
|
|
|
input(Is, L0, C0, L, C) -->
|
|
nonthing(L0, C0, L1, C1), !,
|
|
input(Is, L1, C1, L, C).
|
|
|
|
input(Is) --> input(Is, 0, 0, _, _).
|
|
|
|
|
|
adjacent(LN-CN0-CN1, LS-CS) :-
|
|
LLo is LN - 1, LHi is LN + 1, LS >= LLo, LS =< LHi,
|
|
CLo is CN0 - 1, CHi is CN1 + 1, CS >= CLo, CS =< CHi.
|
|
|
|
part_number(N) :-
|
|
n(N, NLoc), s(_, SLoc), adjacent(NLoc, SLoc).
|
|
|
|
number_next_to(N, SLoc) :-
|
|
n(N, NLoc), adjacent(NLoc, SLoc).
|
|
|
|
gear(Ratio) :-
|
|
s('*', SLoc),
|
|
bagof(N, number_next_to(N, SLoc), [A, B]),
|
|
Ratio is A * B.
|
|
|
|
|
|
parse_setup(File) :- parse(File, Items), setup(Items).
|
|
|
|
parse(File, Items) :- phrase_from_file(input(Items), File), !.
|
|
|
|
setup(Items) :-
|
|
transaction((abolish(n/2), abolish(s/2), maplist(assert, Items))).
|
|
:- dynamic n/2, s/2.
|
|
|
|
sum(Xs, X) :- foldl(plus, Xs, 0, X).
|
|
|
|
part1(File) :-
|
|
parse_setup(File),
|
|
bagof(N, part_number(N), Ns),
|
|
sum(Ns, Total),
|
|
writeln(Total).
|
|
|
|
part2(File) :-
|
|
parse_setup(File),
|
|
bagof(R, gear(R), Rs),
|
|
sum(Rs, Total),
|
|
writeln(Total).
|
|
|
|
% vim: set ft=prolog :
|