aoc23/12/part2.pl

66 lines
2.0 KiB
Perl
Raw Permalink Normal View History

% 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).