aoc23/04/part2.pl

39 lines
1.4 KiB
Perl
Raw Normal View History

2023-12-04 05:16:47 -06:00
:- table match/3.
:- table sum/5.
% Number of card X = Nx = 1 + sum(Ni*(matches(i) >= x-i), i=1->x-1)
ncards([], []).
ncards([_|RestOfCards], [Nx|NRest]) :-
length(RestOfCards, X_minus_1), X is X_minus_1 + 1,
ncards(RestOfCards, NRest),
reverse(RestOfCards, ReversedRestOfCards),
sum(ReversedRestOfCards, X, NRest, _, Nx_minus_1), Nx is Nx_minus_1 + 1.
2023-12-04 11:21:56 -06:00
% sum(Cards, X, StuffToSum, Indices, Sum).
% This calculates the "sum(Ni*(matches(i) >= x-i), i=1->x-1)" part of Nx
sum(_, _, [], [0], 0).
sum(Cards, X, [Element|Rest], [I,INext|IRest], Sum) :-
sum(Cards, X, Rest, [INext|IRest], SumOfRest),
match(Cards, I, NMatches_i),
I is INext + 1,
(NMatches_i >= X - I -> Sum is Element + SumOfRest; Sum is SumOfRest).
% match binds the number of matches that card Nth in the list has
match(Cards, Nth, NMatches) :-
nth1(Nth, Cards, [Wins|CardNums]),
match1(Wins, CardNums, NMatches).
% match1(WinningNums, CardNums, NMatches) binds number of matches for a card.
match1(_, [], 0).
match1(Wins, [X|Nums], M) :- member(X, Wins), match1(Wins, Nums, M1), M is M1 + 1.
match1(Wins, [X|Nums], M) :- \+ member(X, Wins), match1(Wins, Nums, M).
2023-12-04 05:16:47 -06:00
% this is a more normal sum of a list
sum([], 0).
sum([Element|Rest], Sum) :- sum(Rest, RestOfSum), Sum is Element + RestOfSum.
all_scores(Input, Score) :-
reverse(Input, ReversedInput),
ncards(ReversedInput, CardCounts),
sum(CardCounts, Score).