day 5 prolog

This commit is contained in:
chayleaf 2021-12-09 07:01:18 +07:00
parent db07808eb2
commit 6c72571acf
2 changed files with 340 additions and 0 deletions

153
pl/05.1.pl Normal file
View file

@ -0,0 +1,153 @@
parse_line(S, [A, B, C, D]) :-
split_string(S, " ->", "", [X, _, _, _, Y]),
split_string(X, ",", "", [A0, B0]),
split_string(Y, ",", "", [C0, D0]),
number_string(A, A0),
number_string(B, B0),
number_string(C, C0),
number_string(D, D0).
read_file(Stream, []) :-
at_end_of_stream(Stream).
read_file(Stream, [X|L]) :-
\+ at_end_of_stream(Stream),
read_line_to_codes(Stream, C),
string_chars(S, C),
parse_line(S, X),
read_file(Stream, L).
main :-
open('../input/05', read, Stream),
read_file(Stream, Lines), !,
close(Stream),
minmax_seq(Lines, X0, X1, Y0, Y1),
C = [X0 - 10, X1 + 10, Y0 - 10, Y1 + 10],
filter_hor_vert(Lines, L0),
convert_coords(L0, C, L1),
create_grid(C, G), !,
mark_lines(G, L1, G1), !,
count_ge2(G1, W),
print(W).
filter_hor_vert([], []).
filter_hor_vert([A|As], [A|Bs]) :-
(horizontal(A); vertical(A)),
filter_hor_vert(As, Bs).
filter_hor_vert([A|As], B) :-
\+ horizontal(A),
\+ vertical(A),
filter_hor_vert(As, B).
convert_coords([], _, []).
convert_coords([[A0,A1,A2,A3]|As], [X0, X1, Y0, Y1], [[B0,B1,B2,B3]|Bs]) :-
C0 is A0 - X0,
C1 is A1 - Y0,
C2 is A2 - X0,
C3 is A3 - Y0,
B0 is min(C0, C2),
B2 is max(C0, C2),
B1 is min(C1, C3),
B3 is max(C1, C3),
convert_coords(As, [X0, X1, Y0, Y1], Bs).
create_row(0, []).
create_row(X, [0|As]) :-
X > 0,
X1 is X - 1,
create_row(X1, As).
create_grid([X0, X1, Y0, Y1], A) :-
create_grid(X1 - X0 + 1, Y1 - Y0 + 1, A).
create_grid(_, 0, []).
create_grid(X, Y, [A|As]) :-
Y > 0,
Y1 is Y - 1,
create_row(X, A),
create_grid(X, Y1, As).
minmax([A, B, C, D], X0, X1, Y0, Y1) :-
X0 is min(A, C),
X1 is max(A, C),
Y0 is min(B, D),
Y1 is max(B, D).
minmax_seq([A], X0, X1, Y0, Y1) :-
minmax(A, X0, X1, Y0, Y1).
minmax_seq([A|As], X0, X1, Y0, Y1) :-
minmax_seq(As, X00, X01, Y00, Y01),
minmax(A, X10, X11, Y10, Y11),
X0 is min(X00, X10),
X1 is max(X01, X11),
Y0 is min(Y00, Y10),
Y1 is max(Y01, Y11).
vertical([A, _, A, _]).
horizontal([_, A, _, A]).
prefix_n(0, _, []).
prefix_n(X, [A|As], [A|Ps]) :-
X > 0,
X1 is X - 1,
prefix_n(X1, As, Ps), !.
suffix_n(N, A, S) :-
reverse(A, B),
prefix_n(N, B, P),
reverse(P, S), !.
add_one([], []).
add_one([A|As], [B|Bs]) :-
B is A + 1,
add_one(As, Bs), !.
mark_in_row(X, [A, B], Y) :-
length(X, L),
L1 is L - B - 1,
prefix_n(A, X, Pfx),
suffix_n(L1, X, Sfx),
append([Pfx, Q, Sfx], X),
add_one(Q, W),
append([Pfx, W, Sfx], Y), !.
mark_row(X, [A, B, C, B], Y) :-
length(X, L),
L1 is L - B - 1,
prefix_n(B, X, Pfx),
suffix_n(L1, X, Sfx),
nth0(B, X, Row0),
mark_in_row(Row0, [A, C], Row1),
append([Pfx, [Row1], Sfx], Y), !.
mark_cols([], _, []).
mark_cols([X|Xs], A, [Y|Ys]) :-
mark_in_row(X, [A, A], Y), !,
mark_cols(Xs, A, Ys), !.
mark_col(X, [A, B, A, D], Y) :-
length(X, L),
L1 is L - D - 1,
prefix_n(B, X, Pfx),
suffix_n(L1, X, Sfx),
append([Pfx, Q, Sfx], X),
mark_cols(Q, A, W), !,
append([Pfx, W, Sfx], Y).
mark_line(X, Z, Y) :-
(mark_col(X, Z, Y), !); (mark_row(X, Z, Y), !).
mark_lines(X, [], X).
mark_lines(X, [Z|Zs], Y) :-
mark_line(X, Z, Y0), !,
mark_lines(Y0, Zs, Y), !.
count_ge2_row([], 0).
count_ge2_row([A|As], C) :-
A >= 2,
count_ge2_row(As, C1),
C is C1 + 1.
count_ge2_row([A|As], C) :-
A < 2,
count_ge2_row(As, C).
count_ge2([], 0).
count_ge2([X|Xs], Y) :-
count_ge2(Xs, Y0),
count_ge2_row(X, Y1),
Y is Y0 + Y1.

187
pl/05.2.pl Normal file
View file

@ -0,0 +1,187 @@
parse_line(S, [A, B, C, D]) :-
split_string(S, " ->", "", [X, _, _, _, Y]),
split_string(X, ",", "", [A0, B0]),
split_string(Y, ",", "", [C0, D0]),
number_string(A, A0),
number_string(B, B0),
number_string(C, C0),
number_string(D, D0).
read_file(Stream, []) :-
at_end_of_stream(Stream).
read_file(Stream, [X|L]) :-
\+ at_end_of_stream(Stream),
read_line_to_codes(Stream, C),
string_chars(S, C),
parse_line(S, X),
read_file(Stream, L).
main :-
open('../input/05', read, Stream),
read_file(Stream, Lines), !,
close(Stream),
minmax_seq(Lines, X0, X1, Y0, Y1),
C = [X0 - 10, X1 + 10, Y0 - 10, Y1 + 10],
convert_coords(Lines, C, L1),
create_grid(C, G), !,
mark_lines(G, L1, G1), !,
count_ge2(G1, W),
print(W).
convert_coords([], _, []).
convert_coords([[A0,A1,A2,A3]|As], [X0, X1, Y0, Y1], [[B0,B1,B2,B3]|Bs]) :-
C0 is A0 - X0,
C1 is A1 - Y0,
C2 is A2 - X0,
C3 is A3 - Y0,
((
(horizontal([C0, C1, C2, C3]); vertical([C0, C1, C2, C3])),
B0 is min(C0, C2),
B2 is max(C0, C2),
B1 is min(C1, C3),
B3 is max(C1, C3)
);
(
C0 =< C2,
B0 is C0,
B1 is C1,
B2 is C2,
B3 is C3
);
(
C2 < C0,
B0 is C2,
B1 is C3,
B2 is C0,
B3 is C1
)),
convert_coords(As, [X0, X1, Y0, Y1], Bs).
create_row(0, []).
create_row(X, [0|As]) :-
X > 0,
X1 is X - 1,
create_row(X1, As).
create_grid([X0, X1, Y0, Y1], A) :-
create_grid(X1 - X0 + 1, Y1 - Y0 + 1, A).
create_grid(_, 0, []).
create_grid(X, Y, [A|As]) :-
Y > 0,
Y1 is Y - 1,
create_row(X, A),
create_grid(X, Y1, As).
minmax([A, B, C, D], X0, X1, Y0, Y1) :-
X0 is min(A, C),
X1 is max(A, C),
Y0 is min(B, D),
Y1 is max(B, D).
minmax_seq([A], X0, X1, Y0, Y1) :-
minmax(A, X0, X1, Y0, Y1).
minmax_seq([A|As], X0, X1, Y0, Y1) :-
minmax_seq(As, X00, X01, Y00, Y01),
minmax(A, X10, X11, Y10, Y11),
X0 is min(X00, X10),
X1 is max(X01, X11),
Y0 is min(Y00, Y10),
Y1 is max(Y01, Y11).
vertical([A, _, A, _]).
horizontal([_, A, _, A]).
diagonal_a([A, B, C, D]) :-
C - A =:= D - B.
diagonal_b([A, B, C, D]) :-
C - A =:= B - D.
prefix_n(0, _, []).
prefix_n(X, [A|As], [A|Ps]) :-
X > 0,
X1 is X - 1,
prefix_n(X1, As, Ps), !.
suffix_n(N, A, S) :-
reverse(A, B),
prefix_n(N, B, P),
reverse(P, S), !.
add_one([], []).
add_one([A|As], [B|Bs]) :-
B is A + 1,
add_one(As, Bs), !.
mark_in_row(X, [A, B], Y) :-
length(X, L),
L1 is L - B - 1,
prefix_n(A, X, Pfx),
suffix_n(L1, X, Sfx),
append([Pfx, Q, Sfx], X),
add_one(Q, W),
append([Pfx, W, Sfx], Y), !.
mark_row(X, [A, B, C, B], Y) :-
length(X, L),
L1 is L - B - 1,
prefix_n(B, X, Pfx),
suffix_n(L1, X, Sfx),
nth0(B, X, Row0),
mark_in_row(Row0, [A, C], Row1),
append([Pfx, [Row1], Sfx], Y), !.
mark_cols([], _, []).
mark_cols([X|Xs], A, [Y|Ys]) :-
mark_in_row(X, [A, A], Y), !,
mark_cols(Xs, A, Ys), !.
mark_col(X, [A, B, A, D], Y) :-
length(X, L),
L1 is L - D - 1,
prefix_n(B, X, Pfx),
suffix_n(L1, X, Sfx),
append([Pfx, Q, Sfx], X),
mark_cols(Q, A, W), !,
append([Pfx, W, Sfx], Y).
mark_diag_a(X, [A, B, A, B], Y) :-
mark_row(X, [A, B, A, B], Y).
mark_diag_a(X, [A, B, C, D], Y) :-
A \= C,
diagonal_a([A, B, C, D]),
mark_diag_a(X, [A, B, A, B], Y0),
A1 is A + 1,
B1 is B + 1,
mark_diag_a(Y0, [A1, B1, C, D], Y).
mark_diag_b(X, [A, B, A, B], Y) :-
mark_row(X, [A, B, A, B], Y).
mark_diag_b(X, [A, B, C, D], Y) :-
A \= C,
diagonal_b([A, B, C, D]),
mark_diag_b(X, [A, B, A, B], Y0),
A1 is A + 1,
B1 is B - 1,
mark_diag_b(Y0, [A1, B1, C, D], Y).
mark_line(X, Z, Y) :-
(mark_col(X, Z, Y), !);
(mark_row(X, Z, Y), !);
(mark_diag_a(X, Z, Y), !);
(mark_diag_b(X, Z, Y), !).
mark_lines(X, [], X).
mark_lines(X, [Z|Zs], Y) :-
mark_line(X, Z, Y0), !,
mark_lines(Y0, Zs, Y), !.
count_ge2_row([], 0).
count_ge2_row([A|As], C) :-
A >= 2,
count_ge2_row(As, C1),
C is C1 + 1.
count_ge2_row([A|As], C) :-
A < 2,
count_ge2_row(As, C).
count_ge2([], 0).
count_ge2([X|Xs], Y) :-
count_ge2(Xs, Y0),
count_ge2_row(X, Y1),
Y is Y0 + Y1.