aoc2021/pl/04.2.pl

142 lines
3.2 KiB
Perl
Raw Permalink Normal View History

2021-12-09 04:30:09 +07:00
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(X, C),
read_file(Stream, L).
split1([], [], []).
split1([""|As], [], As). % starts with "" -> [], seq end
split1([A|As], [A|Bs], X) :-
A \= "",
split1(As, Bs, X).
split2([], []).
split2([A|As], [B|Bs]) :-
split1([A|As], B, C),
split2(C, Bs).
remove_x(_, [], []).
remove_x(X, [X|As], Bs) :-
remove_x(X, As, Bs).
remove_x(X, [A|As], [A|Bs]) :-
A \= X,
remove_x(X, As, Bs).
numbers_strings([], []).
numbers_strings([A|As], [B|Bs]) :-
number_string(A, B),
numbers_strings(As, Bs).
strings_board([], []).
strings_board([A|As], [B|Bs]) :-
split_string(A, " ", "", C),
remove_x("", C, D),
numbers_strings(B, D),
strings_board(As, Bs).
stringss_boards([], []).
stringss_boards([A|As], [B|Bs]) :-
strings_board(A, B),
stringss_boards(As, Bs).
parse_boards(L, A) :-
split2(L, B),
remove_x([], B, C),
stringss_boards(C, A).
parse_file([X|L], N, B) :-
split_string(X, ",", "", A),
numbers_strings(N, A),
parse_boards(L, B).
main :-
open('../input/04', read, Stream),
read_file(Stream, Lines), !,
close(Stream),
parse_file(Lines, A, B),
solve(A, B, C),
print(C).
mark_nums_row(_, [], []).
mark_nums_row(N, [R|Rs], [1|Xs]) :-
append([_, [R], _], N),
mark_nums_row(N, Rs, Xs).
mark_nums_row(N, [R|Rs], [0|Xs]) :-
\+ append([_, [R], _], N),
mark_nums_row(N, Rs, Xs).
mark_nums_board(_, [], []).
mark_nums_board(N, [B|Bs], [C|Cs]) :-
mark_nums_row(N, B, C),
mark_nums_board(N, Bs, Cs).
rows_win([R|Rs]) :-
(R = [1,1,1,1,1]; rows_win(Rs)).
transpose([[]|_], []).
transpose(A, [B|Bs]) :-
first_column(A, B, C),
transpose(C, Bs).
first_column([], [], []).
first_column([[B|C]|As], [B|Bs], [C|Cs]) :-
first_column(As, Bs, Cs).
marked_board_win(B) :-
rows_win(B).
marked_board_win(B) :-
transpose(B, T),
rows_win(T).
unmarked_row_sum([], [], 0).
unmarked_row_sum([_|As], [1|Ms], C) :-
unmarked_row_sum(As, Ms, C).
unmarked_row_sum([A|As], [0|Ms], C) :-
unmarked_row_sum(As, Ms, C1),
C is A + C1.
unmarked_board_sum([], [], 0).
unmarked_board_sum([A|As], [B|Bs], C) :-
unmarked_row_sum(A, B, C1),
unmarked_board_sum(As, Bs, C2),
C is C1 + C2.
last_num([R], R).
last_num([_|Rs], X) :-
last_num(Rs, X).
board_win(N, B, X) :-
mark_nums_board(N, B, C),
marked_board_win(C),
unmarked_board_sum(B, C, Z),
last_num(N, Y),
X is Y * Z.
win_order(_, [], [], []).
win_order(N, [B|Bs], C, [B|Rs]) :-
\+ board_win(N, B, _),
win_order(N, Bs, C, Rs).
win_order(N, [B|Bs], [C|Cs], R) :-
board_win(N, B, C),
win_order(N, Bs, Cs, R).
step_win_order(N, B, C) :-
step_win_order(N, [], B, C).
step_win_order(_, _, [], []).
step_win_order([A|As], [], B, C) :-
step_win_order(As, [A], B, C).
step_win_order([A|As], [N|Ns], B, C) :-
win_order([N|Ns], B, C0, R),
append([N|Ns], [A], D),
step_win_order(As, D, R, C1),
append(C0, C1, C).
step_win_order([], N, B, C) :-
win_order(N, B, C, _).
solve(N, B, C) :-
step_win_order(N, B, D),
last_num(D, C).