Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day 7

Day7.livemd

Day 7

Mix.install([
  {:kino_aoc, "~> 0.1.5"},
  {:nimble_parsec, "~> 1.4"}
])

Part 1

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "7", System.fetch_env!("LB_AOC_SESSION"))
puzzle_input
|> String.split("\n")
|> Enum.map(&String.split(&1, " "))
|> Enum.map(fn [hand, bid] ->
  hand =
    hand
    |> String.graphemes()
    |> Enum.map(fn
      "T" -> 10
      "J" -> 11
      "Q" -> 12
      "K" -> 13
      "A" -> 14
      i -> String.to_integer(i)
    end)

  hand_sets =
    hand
    |> Enum.group_by(& &1)
    |> Enum.map(fn {k, g} -> {Enum.count(g), k} end)
    |> Enum.sort(:desc)
    |> Enum.map(&elem(&1, 0))

  {hand_sets, hand, String.to_integer(bid)}
end)
|> Enum.sort_by(&{elem(&1, 0), elem(&1, 1)})
|> Enum.with_index(1)
|> Enum.map(fn {{_, _, bid}, rank} -> bid * rank end)
|> Enum.sum()

Part 2

puzzle_input
|> String.split("\n")
|> Enum.map(&String.split(&1, " "))
|> Enum.map(fn [hand, bid] ->
  hand =
    hand
    |> String.graphemes()
    |> Enum.map(fn
      "T" -> 10
      "J" -> 1
      "Q" -> 12
      "K" -> 13
      "A" -> 14
      i -> String.to_integer(i)
    end)

  {jokers, hand_sets} =
    hand
    |> Enum.group_by(& &1)
    |> Enum.map(fn {k, g} -> {Enum.count(g), k} end)
    |> Enum.sort(:desc)
    |> Enum.split_with(fn {_, card} -> card == 1 end)

  {most, best_card} = Enum.at(hand_sets, 0, {0, 1})

  rest =
    if Enum.empty?(hand_sets) do
      []
    else
      tl(hand_sets)
    end

  hand_sets =
    [{most + (jokers |> Enum.at(0, {0, 1}) |> elem(0)), best_card} | rest]
    |> Enum.map(&elem(&1, 0))

  {hand_sets, hand, String.to_integer(bid)}
end)
|> Enum.sort_by(&{elem(&1, 0), elem(&1, 1)})
|> Enum.with_index(1)
|> Enum.map(fn {{_, _, bid}, rank} -> bid * rank end)
|> Enum.sum()
String.codepoints("AAJ99")
|> Enum.group_by(& &1)
|> Enum.map(fn {k, g} -> {Enum.count(g), k} end)
|> Enum.sort(:desc)