Skip to content

Day 07: Camel Cards

We need to sort the given hands of cards on signature first, then card value. The signature is [5] for a five-of-a-kind, [3, 2] for full-house, [2, 2, 1] for two pairs ... etc.

The count_elements function counts how many copies of each unique element is in a collection.

#day07
function count_elements(coll)
  groups = Dict()
  for el in coll
    groups[el] = get(groups, el, 0) + 1
  end
  groups
end

Then the signature function gets those counts and sorts them. We return [0] for empty collections, a useful choice for part 2.

#day07
function signature(hand)
  if isempty(hand)
    return [0]
  end
  sort!(collect(values(count_elements(hand))); rev=true)
end

The trick with part two is to find the signature of the hand without jokers and then increase the leading value to a total of five.

Main
file: src/Day07.jl
module Day07

using ..Parsing: token, match_p, integer, fmap, starmap, sequence, some_p

struct Bid
  hand::String
  amount::Int
end

bid_p = sequence(
  token(r"[2-9TJQKA]+") >> fmap(m -> m.match),
  integer) >> starmap(Bid)

<<day07>>

function hand_score(hand::AbstractString)
  card_values = Dict(zip("23456789TJQKA", 1:13))
  int_hand = [card_values[c] for c in hand]
  return (signature(hand), int_hand)
end

function joker_hand_score(hand::AbstractString)
  card_values = Dict(zip("J23456789TQKA", 1:13))
  int_hand = [card_values[c] for c in hand]
  short_hand = replace(hand, "J" => "")
  sign = signature(short_hand)
  sign[1] += 5 - length(short_hand)
  return (sign, int_hand)
end

function main(io::IO)
  input = readlines(io) .|> (first  bid_p)
  sort!(input; by=b -> hand_score(b.hand))
  println("Part 1: ", sum(i * h.amount for (i, h) in enumerate(input)))
  sort!(input; by=b -> joker_hand_score(b.hand))
  println("Part 2: ", sum(i * h.amount for (i, h) in enumerate(input)))
end

end
Test
#test
@testset "day 7" begin
  using AOC2023.Day07: bid_p, hand_score, joker_hand_score
  input = """
  32T3K 765
  T55J5 684
  KK677 28
  KTJJT 220
  QQQJA 483"""
  bids = split(strip(input), "\n") .|> (first  bid_p)
  sort!(bids; by=b -> hand_score(b.hand))
  @test sum(i * h.amount for (i, h) in enumerate(bids)) == 6440
  sort!(bids; by=b -> joker_hand_score(b.hand))
  @test sum(i * h.amount for (i, h) in enumerate(bids)) == 5905
end
Part 1: 255048101
Part 2: 253718286