136 lines
3.1 KiB
Perl
136 lines
3.1 KiB
Perl
|
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),
|
||
|
step_first_board_win(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) :-
|
||
|
transpose(B, T),
|
||
|
(rows_win(B); 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.
|
||
|
|
||
|
first_board_win(N, [B|_], C) :-
|
||
|
board_win(N, B, C).
|
||
|
|
||
|
first_board_win(N, [B|Bs], C) :-
|
||
|
\+ board_win(N, B, _),
|
||
|
first_board_win(N, Bs, C).
|
||
|
|
||
|
step_first_board_win([A|As], [], B, C) :-
|
||
|
step_first_board_win(As, [A], B, C).
|
||
|
step_first_board_win([_|_], [N|Ns], B, C) :-
|
||
|
first_board_win([N|Ns], B, C).
|
||
|
step_first_board_win([A|As], [N|Ns], B, C) :-
|
||
|
\+ first_board_win([N|Ns], B, _),
|
||
|
append([N|Ns], [A], D),
|
||
|
step_first_board_win(As, D, B, C).
|
||
|
step_first_board_win([], N, B, C) :-
|
||
|
first_board_win(N, B, C).
|
||
|
|
||
|
step_first_board_win(N, B, C) :-
|
||
|
step_first_board_win(N, [], B, C).
|