2023 Advent of Code Day 7 Part 2
Perl. Developed and tested with Perl 5.38.0.
use v5.38; use Hash::MultiKey; use feature q/switch/; no warnings q/deprecated/; use constant CAMEL_CARDS => A => 12, K => 11, Q => 10, T => 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, J => 0; sub camel_card_sorter{ my %h = CAMEL_CARDS; my @a = split q//, $a; my @b = split q//, $b; { my $s = shift @a; my $t = shift @b; return $h{$s} <=> $h{$t} if $s ne $t; redo unless !@a || !@b; } } sub camel_hands{ my $hand = shift; my %h; tie %h, q/Hash::MultiKey/; $h{[5]} = 6; $h{[1, 4]} = 5; $h{[2, 3]} = 4; $h{[1, 1, 3]} = 3; $h{[1, 2, 2]} = 2; $h{[1, 1, 1, 2]} = 1; $h{[1, 1, 1, 1, 1]} = 0; my %hand; my $jokers = $hand =~ tr/J//d; do{$hand{$_}++} for split q//, $hand; my @cards_by_count = sort {$hand{$b} <=> $hand{$a}} keys %hand; given($jokers){ when($_ == 0){ break; } when($_ >= 1 && $_ < 5){ my $card_most = $cards_by_count[0]; my $s = $card_most x ($_ + 1); $hand =~ s/$card_most/$s/; } when($_ == 5){ $hand = q/A/ x 5; } } %hand = (); do{$hand{$_}++} for split q//, $hand; return $h{[sort {$a <=> $b} values %hand]}; } sub camel_hand_ranking{ my $camel_hand_sorter = sub{ my $c = camel_hands($a) <=> camel_hands($b); return $c unless !$c; return camel_card_sorter $a, $b; }; return sort $camel_hand_sorter @_; } MAIN:{ open(DATA, q/data/); my @hands; my %hand_bids; do{ chop; my($hand, $bid) = split /\s/, $_; push @hands, $hand; $hand_bids{$hand} = $bid; } for <DATA>; my @hands_sorted = camel_hand_ranking(@hands); my $total_winnings = 0; do{ my $hand = $hands_sorted[$_ - 1]; $total_winnings += $_ * $hand_bids{$hand}; } for 1 .. @hands_sorted; say $total_winnings; }