aoc23/07/part2.pl
2023-12-07 15:04:57 -08:00

55 lines
2.1 KiB
Prolog

answer(Answer) :-
input(Input), convert_input(Input, Hands, Bets),
convlist(score, Hands, Scores),
zip(Scores, Bets, ScoresBets),
sort(ScoresBets, SortedScoreBets),
length(Input, NHands), length(VarList, NHands),
scanl([_, Prev, Curr]>>(Curr is Prev + 1), VarList, 0, [_ | Ranks]),
zip(Ranks, SortedScoreBets, RankScoreBets),
foldl([Rank-(_-Bet), Prev, Sum]>>(Sum is Prev + Rank*Bet),
RankScoreBets, 0, Answer).
% score(Hand, Score) gets the score for one hand, that can be directly compared.
score([A, B, C, D, E], Score) :-
type([A, B, C, D, E], Type),
Score is E + 100*D + (100**2)*C + (100**3)*B + (100**4)*A + (100**5)*Type.
type([1, 1, 1, 1, 1], 7).
type(Hand, 7) :- count_hand(Hand, 5, _).
type(Hand, 6) :- count_hand(Hand, 4, _).
type(Hand, 5) :- count_hand(Hand, 3, 2).
type(Hand, 4) :- count_hand(Hand, 3, 3).
type(Hand, 3) :- count_hand(Hand, 2, 3).
type(Hand, 2) :- count_hand(Hand, 2, 4).
type(Hand, 1) :- count_hand(Hand, 1, _).
count_hand(Hand, NMaxCard, NUniqueCards) :-
exclude(=:=(1), Hand, NoJokerHand),
maplist(count(NoJokerHand), NoJokerHand, Counts),
max_member(MaxCountNoJoker, Counts),
count(Hand, 1, NJokers),
NMaxCard is MaxCountNoJoker + NJokers,
sort(NoJokerHand, Uniques), length(Uniques, NUniqueCards).
% count(List, Elem, Count), Count = number of occurences of Elem in List.
count([], _, 0).
count([X | Cdr], X, N) :- count(Cdr, X, NRest), N is NRest + 1.
count([Y | Rest], X, N) :- Y =\= X, count(Rest, X, N).
% card(Ascii, Value) converts between card ascii value and internal values
card(74, 1). % J
card(84, 10). card(81, 12). card(75, 13). card(65, 14). % TQKA
card(Char, Card) :- Char >= 48, Char =< 57, Card is Char - 48.
% zip 2 lists into a map
zip(List1, List2, Map) :- maplist([A, B, A-B]>>(true), List1, List2, Map).
% convert_input(InputList, Cards, Bets)
convert_input([], [], []).
convert_input([[Cards, Bet] | Cdr],
[[C1, C2, C3, C4, C5] | HandCdr],
[Bet | BetCdr]) :-
string_to_list(Cards, [A1, A2, A3, A4, A5]),
card(A1, C1), card(A2, C2), card(A3, C3), card(A4, C4), card(A5, C5),
convert_input(Cdr, HandCdr, BetCdr).