aoc2023/day3.pl

82 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 :