diff --git a/pl/04.1.pl b/pl/04.1.pl new file mode 100644 index 0000000..f35d756 --- /dev/null +++ b/pl/04.1.pl @@ -0,0 +1,135 @@ +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). diff --git a/pl/04.2.pl b/pl/04.2.pl new file mode 100644 index 0000000..656bbf2 --- /dev/null +++ b/pl/04.2.pl @@ -0,0 +1,141 @@ +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).