aoc2021/pl/09.2.pl

174 lines
4.4 KiB
Perl
Raw Normal View History

2021-12-09 14:01:39 +07:00
chars_digits([], []).
chars_digits([A|As], [B|Bs]) :-
char_type(A, digit(B)),
chars_digits(As, Bs).
read_file(Stream, []) :-
at_end_of_stream(Stream).
read_file(Stream, [X|Xs]) :-
\+ at_end_of_stream(Stream),
read_line_to_codes(Stream, C),
chars_digits(C, X),
read_file(Stream, Xs).
main :-
open('../input/09', read, Stream),
read_file(Stream, Lines), !,
close(Stream),
low_points(Lines, Res),
basins(Lines, Res, B0),
msort(B0, B1),
reverse(B1, [B2,B3,B4|_]),
X is B2 * B3 * B4,
print(X).
basins(_, [], []).
basins(A, [P|Ps], [B|Bs]) :-
points_high_neighbors_all(A, [P], Bas),
length(Bas, B),
basins(A, Ps, Bs).
low_point([[A,B|_]|[[C|_]|_]], 0, 0) :-
A < B, A < C.
low_point([A|As], X, 0) :-
X > 0,
nth0(X, A, R0),
X0 is X - 1,
X1 is X + 1,
nth0(X0, A, R1),
R0 < R1,
(
(length(A, X1), length([A|As], 1));
(length([A|As], 1), nth0(X1, A, R2), R0 < R2);
(length(A, X1), nth0(1, [A|As], E), nth0(X, E, E0), R0 < E0);
(nth0(X1, A, R2), R0 < R2, nth0(1, [A|As], E), nth0(X, E, E0), R0 < E0)
).
low_point(A, 0, Y) :-
Y > 0,
nth0(Y, A, [R0,R1|_]),
R0 < R1,
Y0 is Y - 1,
Y1 is Y + 1,
nth0(Y0, A, [T0|_]),
R0 < T0,
(
length(A, Y1);
(nth0(Y1, A, [E0|_]), R0 < E0)
).
low_point(A, X, Y) :-
Y > 0,
X > 0,
nth0(Y, A, R),
nth0(X, R, R0),
X0 is X - 1,
Y0 is Y - 1,
X1 is X + 1,
Y1 is Y + 1,
nth0(X0, R, R1),
R0 < R1,
nth0(Y0, A, E),
nth0(X, E, E0),
R0 < E0,
(
(length(A, Y1), length(R, X1));
(length(A, Y1), nth0(X1, R, R2), R0 < R2);
(length(R, X1), nth0(Y1, A, T), nth0(X, T, T0), R0 < T0);
(nth0(X1, R, R2), R0 < R2, nth0(Y1, A, T), nth0(X, T, T0), R0 < T0)
).
low_points([A|As], Ret) :-
length([A|As], Y),
length(A, X),
X0 is X - 1,
Y0 is Y - 1,
low_points([A|As], X0, Y0, Ret).
low_points(A, 0, 0, [[0, 0]]) :-
low_point(A, 0, 0).
low_points(A, 0, 0, []) :-
\+ low_point(A, 0, 0).
low_points(A, X, Y, [[X, Y]|Rs]) :-
X > 0,
low_point(A, X, Y),
X0 is X - 1,
low_points(A, X0, Y, Rs).
low_points(A, X, Y, Rs) :-
X > 0,
\+ low_point(A, X, Y),
X0 is X - 1,
low_points(A, X0, Y, Rs).
low_points([A|As], 0, Y, [[0, Y]|Rs]) :-
Y > 0,
length(A, Len),
low_point([A|As], 0, Y),
Y0 is Y - 1,
X0 is Len - 1,
low_points([A|As], X0, Y0, Rs).
low_points([A|As], 0, Y, Rs) :-
Y > 0,
length(A, Len),
\+ low_point([A|As], 0, Y),
Y0 is Y - 1,
X0 is Len - 1,
low_points([A|As], X0, Y0, Rs).
high_neighbor(A, [X1, Y1], [X0, Y0]) :-
nth0(Y1, A, R1),
nth0(Y0, A, R0),
nth0(X1, R1, A1),
A1 =\= 9,
nth0(X0, R0, A0),
A1 > A0.
high_neighbors(A, X, Y, P) :-
valid_paths(A, X, Y, W),
setof(Q, (member(Q, W), high_neighbor(A, Q, [X, Y])), P).
high_neighbors(A, X, Y, []) :-
valid_paths(A, X, Y, W),
\+ setof(Q, (member(Q, W), high_neighbor(A, Q, [X, Y])), _).
points_high_neighbors(_, [], []).
points_high_neighbors(A, [[X,Y]|Ps], N) :-
points_high_neighbors(A, Ps, N1),
high_neighbors(A, X, Y, N0),
append(N0, N1, N2),
sort(N2, N).
points_high_neighbors_all(A, P, P) :-
points_high_neighbors(A, P, []).
points_high_neighbors_all(A, P, N) :-
points_high_neighbors(A, P, N1),
points_high_neighbors_all(A, N1, N2),
append(P, N2, N3),
sort(N3, N).
in_bounds(W, H, X, Y) :-
X >= 0, X < W,
Y >= 0, Y < H.
valid_paths([A|As], X, Y, P) :-
length([A|As], H),
length(A, W),
valid_paths(W, H, X, Y, P).
valid_paths(W, H, X, Y, [P|Ps]) :-
X0 is X - 1, in_bounds(W, H, X0, Y), P = [X0, Y], valid_paths_1(W, H, X, Y, Ps).
valid_paths(W, H, X, Y, Ps) :-
X0 is X - 1,
\+ in_bounds(W, H, X0, Y),
valid_paths_1(W, H, X, Y, Ps).
valid_paths_1(W, H, X, Y, [P|Ps]) :-
X0 is X + 1, in_bounds(W, H, X0, Y), P = [X0, Y], valid_paths_2(W, H, X, Y, Ps).
valid_paths_1(W, H, X, Y, Ps) :-
X0 is X + 1, \+ in_bounds(W, H, X0, Y), valid_paths_2(W, H, X, Y, Ps).
valid_paths_2(W, H, X, Y, [P|Ps]) :-
Y0 is Y - 1, in_bounds(W, H, X, Y0), P = [X, Y0], valid_paths_3(W, H, X, Y, Ps).
valid_paths_2(W, H, X, Y, Ps) :-
Y0 is Y - 1, \+ in_bounds(W, H, X, Y0), valid_paths_3(W, H, X, Y, Ps).
valid_paths_3(W, H, X, Y, [P]) :-
Y0 is Y + 1, in_bounds(W, H, X, Y0), P = [X, Y0].
valid_paths_3(W, H, X, Y, []) :-
Y0 is Y + 1, \+ in_bounds(W, H, X, Y0).