Those who need a refresh can read the problem here.
We are playing poker Camel Cards today! In Part 1 we need to evalute hands and put them in order. Each
hand has what I call a pattern value: five of a kind, poker, full house, three of a kind, double
pair or pair and some individual card value such as: 1, 2, ..., J, Q, K, or A.
Pattern value becomes one number, card value becomes an other number then let linq do the ordering for me.
Part 2 is not much different, but the individual card value changes, and J
becomes
a joker that can replace any other cards. I made a shortcut here and just reused the functions from Part 1.
namespace AdventOfCode.Y2023.Day07;
using System;
using System.Collections.Generic;
using System.Linq;
[ProblemName("Camel Cards")]
class Solution : Solver {
// Each 'hand' gets points based on the card's individual value and
// pattern value.
public object PartOne(string input) => Solve(input, Part1Points);
public object PartTwo(string input) => Solve(input, Part2Points);
(long, long) Part1Points(string hand) =>
(PatternValue(hand), CardValue(hand, "123456789TJQKA"));
(long, long) Part2Points(string hand) {
var cards = "J123456789TQKA";
var patternValue =
cards.Select(ch => PatternValue(hand.Replace('J', ch))).Max();
return (patternValue, CardValue(hand, cards));
}
// map cards to their indices in cardOrder. E.g. for 123456789TJQKA
// A8A8A becomes (13)(7)(13)(7)(13), 9A34Q becomes (8)(13)(2)(3)(11)
long CardValue(string hand, string cardOrder) =>
Pack(hand.Select(card => cardOrder.IndexOf(card)));
// map cards to the number of their occurrences in the hand then order them
// such thatA8A8A becomes 33322, 9A34Q becomes 11111 and K99AA becomes 22221
long PatternValue(string hand) =>
Pack(hand.Select(card => hand.Count(x => x == card)).OrderDescending());
long Pack(IEnumerable<int> numbers) =>
numbers.Aggregate(1L, (a, v) => (a * 256) + v);
int Solve(string input, Func<string, (long, long)> getPoints) {
var bidsByRanking = (
from line in input.Split("\n")
let hand = line.Split(" ")[0]
let bid = int.Parse(line.Split(" ")[1])
orderby getPoints(hand)
select bid
);
return bidsByRanking.Select((bid, rank) => (rank + 1) * bid).Sum();
}
}
Please ☆ my repo if you like it!