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

Advent of Code 2023 Day 7 Part 1

2023_day7_part2.livemd

Advent of Code 2023 Day 7 Part 1

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

Get Inputs

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "7", System.fetch_env!("LB_SESSION"))

My answer

defmodule Resolver do
  @card_strength %{
    "T" => 10,
    "J" => 1,
    "Q" => 12,
    "K" => 13,
    "A" => 14
  }

  def parse(input) do
    input
    |> String.split("\n")
    |> Enum.map(fn line ->
      line
      |> String.split(" ", trim: true)
      |> then(fn [hand, bet] ->
        hand =
          hand
          |> String.codepoints()
          |> Enum.map(fn card ->
            strength = Map.get(@card_strength, card)

            if is_nil(strength) do
              String.to_integer(card)
            else
              strength
            end
          end)

        has_j = Enum.member?(hand, 1)

        {min_freq, max_freq, uniq} =
          hand
          |> Enum.filter(&(&1 != 1))
          |> Enum.frequencies()
          |> Map.values()
          |> then(fn frequencies ->
            if frequencies == [] do
              {0, 0, 0}
            else
              {
                Enum.min(frequencies),
                Enum.max(frequencies),
                Enum.count(frequencies)
              }
            end
          end)

        type_strength =
          case {min_freq, max_freq, uniq, has_j} do
            {_, _, 0, _} ->
              6

            {_, _, 1, _} ->
              6

            {2, _, 2, _} ->
              4

            {_, _, 2, _} ->
              5

            {_, 3, 3, false} ->
              3

            {_, 2, 3, false} ->
              2

            {_, _, 3, true} ->
              3

            {_, _, 4, _} ->
              1

            {_, _, 5, _} ->
              0
          end

        hand_strength =
          0..4
          |> Enum.map(fn index ->
            Enum.at(hand, index) * Integer.pow(14, 4 - index)
          end)
          |> Enum.sum()
          |> Kernel.+(type_strength * Integer.pow(14, 5))

        %{
          hand_strength: hand_strength,
          bet: String.to_integer(bet)
        }
      end)
    end)
  end

  def resolve(games) do
    games
    |> Enum.sort(&amp;(&amp;1.hand_strength < &amp;2.hand_strength))
    |> Enum.with_index()
    |> Enum.map(fn {game, index} ->
      game.bet * (index + 1)
    end)
    |> Enum.sum()
  end
end
games =
  """
  32T3K 765
  T55J5 684
  KK677 28
  KTJJT 220
  QQQJA 483
  """
  |> String.slice(0..-2)
  |> Resolver.parse()
Resolver.resolve(games)
games = Resolver.parse(puzzle_input)
Resolver.resolve(games)