01020304050607080910111213141516171819202122232425

Advent of Code

2023/7

Camel Cards

in C#

by encse

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!

© 2025 Advent of Code is a registered trademark in the US Images provided by Bing image creator