From da1707b36559085b5ae660b2b250dbd56a909883 Mon Sep 17 00:00:00 2001 From: Dory Date: Tue, 12 Dec 2023 11:50:35 -0800 Subject: [PATCH] d12p2. It was actually good; swipl's memoization table just didn't work. --- 12/part1.pl | 1 + 12/part2.naive.pl | 63 --------------------------------------------- 12/part2.pl | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 63 deletions(-) delete mode 100644 12/part2.naive.pl create mode 100644 12/part2.pl diff --git a/12/part1.pl b/12/part1.pl index 16e6da2..9f89583 100644 --- a/12/part1.pl +++ b/12/part1.pl @@ -1,3 +1,4 @@ +% Usage: swipl part1.pl input.txt :- use_module(library(pio)). :- use_module(library(dcg/basics)). :- initialization(main, main). diff --git a/12/part2.naive.pl b/12/part2.naive.pl deleted file mode 100644 index f11f0af..0000000 --- a/12/part2.naive.pl +++ /dev/null @@ -1,63 +0,0 @@ -:- use_module(library(pio)). -:- use_module(library(dcg/basics)). -:- initialization(main, main). -:- table nbads/2. -:- table bads_or_unks/1. -% :- table resolve/3. - -test :- main(['test.txt']). - -main([FileName | _]) :- - input(FileName, Lines), - % TrySolve = [Line-Bads, Prev, Curr]>>( - % writef('%t, %t', [Line, Bads]), - % resolve(Line, Bads, N), - % Curr is Prev + N, - % writef(' --> %t\n', [N])), - % foldl(TrySolve, Lines, 0, Ns), - TrySolve = [Line-Bads, N]>>( - resolve(Line, Bads, N), - writef('%t <-- %t, %t\n', [N, Line, Bads])), - concurrent_maplist(TrySolve, Lines, Ns), - sum_list(Ns, Count), - writef('\nRes=%w, %w\n', [Ns, Count]). - -% Bads is list of contiguous blocks of bad items in Xs; w/unks resolved in Y. -resolve([], [], 1). -resolve([good|Xs], Bads, Y) :- resolve(Xs, Bads, Y). -resolve([unk|Xs], Bads, Y) :- - convlist({Xs, Bads}/[Choice, Yx]>>(resolve([Choice|Xs], Bads, Yx)), - [good, bad], Ys), - sum_list(Ys, Y). -resolve([bad|Xs], [N|Bads], Y) :- - length(BadsUnks, N), - append(BadsUnks, [Next|RemainingXs], [bad|Xs]), - (Next = good; Next = unk), - bads_or_unks(BadsUnks), - resolve(RemainingXs, Bads, Y). - -% List contains all bads or unks -bads_or_unks([]). -bads_or_unks([bad|List]) :- bads_or_unks(List). -bads_or_unks([unk|List]) :- bads_or_unks(List). - -% List contains exactly N bad items. -nbads([], 0). -nbads([bad|List], N) :- N > 0, Remain is N - 1, nbads(List, Remain). - -% read input file into [(good;bad;unk)]-[list of bad runs] -input(FileName, Lines) :- phrase_from_file(lines(Lines), FileName). - -lines([]) --> eos. -lines([Status-Parity|Lines]) --> - (status(S), {append([S, [unk], S, [unk], S, [unk], S, [unk], S, [good]], Status)}), - (parity(P), {append([P, P, P, P, P], Parity)}), - lines(Lines). - -status([]) --> " ". -status([good|Cdr]) --> ".", status(Cdr). -status([bad|Cdr]) --> "#", status(Cdr). -status([unk|Cdr]) --> "?", status(Cdr). - -parity([N]) --> number(N), ("\n"; eos). -parity([N|Cdr]) --> number(N), ",", parity(Cdr). diff --git a/12/part2.pl b/12/part2.pl new file mode 100644 index 0000000..445f268 --- /dev/null +++ b/12/part2.pl @@ -0,0 +1,65 @@ +% Usage: swipl part2.pl input.txt +:- use_module(library(pio)). +:- use_module(library(dcg/basics)). +:- initialization(main, main). + +test :- main(['test.txt']). + +main([FileName | _]) :- + input(FileName, Lines), + concurrent_maplist(resolve_repeated, Lines, Ns), + sum_list(Ns, Count), + writef('Res=%w\n', [Count]). + +resolve_repeated(Line-Bads, N) :- + append([Line, [?], Line, [?], Line, [?], Line, [?], Line], L5), + append([Bads, Bads, Bads, Bads, Bads], B5), + abolish_private_tables, table(resolve/2), + resolve(L5-B5, N). + +% Bads is list of contiguous blocks of bad items in Xs; w/unks resolved in Y. +resolve([]-[], 1). +resolve([o|Xs]-Bads, Y) :- resolve(Xs-Bads, Y). +resolve([?|Xs]-Bads, Y) :- + findall(N, (resolve([o|Xs]-Bads, N); resolve([#|Xs]-Bads, N)), Ys), + sum_list(Ys, Y). +resolve([#|Xs]-[N|Bads], Y) :- + length(BadsUnks, N), + ( append(BadsUnks, [], [#|Xs]), + RemainingXs = [] + ; append(BadsUnks, [Next|RemainingXs], [#|Xs]), (Next = o; Next = ?) + ), + bads_or_unks(BadsUnks), + resolve(RemainingXs-Bads, Y). + +% List contains all bads or unks +bads_or_unks([]). +bads_or_unks([#|List]) :- bads_or_unks(List). +bads_or_unks([?|List]) :- bads_or_unks(List). + +% List contains exactly N bad items. +nbads([], 0). +nbads([#|List], N) :- N > 0, Remain is N - 1, nbads(List, Remain). + +processed_line(1, Line-Bads, NewLine-NewBads) :- + append(Line, [o], NewLine), + NewBads = Bads. + +% read input file into [(o;#;?)]-[list of bad runs] +input(FileName, Lines) :- phrase_from_file(lines(Lines), FileName). + +lines([]) --> eos. +lines([Status-Parity|Lines]) --> status(Status), parity(Parity), lines(Lines). + +status([]) --> " ". +status([o]) --> all_dots, " ". +status([o, #|Cdr]) --> all_dots, "#", status(Cdr). +status([o, ?|Cdr]) --> all_dots, "?", status(Cdr). +status([#|Cdr]) --> "#", status(Cdr). +status([?|Cdr]) --> "?", status(Cdr). + +all_dots --> ".". +all_dots --> ".", all_dots. + +parity([N]) --> number(N), ("\n"; eos). +parity([N|Cdr]) --> number(N), ",", parity(Cdr).