diff --git a/pl/05.2.pl b/pl/05.2.pl new file mode 100644 index 0000000..6bf503c --- /dev/null +++ b/pl/05.2.pl @@ -0,0 +1,188 @@ +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), + %open('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. + +applicable(A) :- + (vertical(A); horizontal(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_diag_a(X, [A, A, A, A], Y) :- + mark_row(X, [A, A, A, A], 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, A, A, A], Y) :- + mark_row(X, [A, A, A, A], 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.