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

Day 7

2023/day07.livemd

Day 7

Mix.install([
  {:kino, "~> 0.11.0"}
])

Section

input = Kino.Input.textarea("input")
defmodule CamelCards do
  def score(bids, deck, joker_value \\ 0) do
    bids
    |> Enum.map(fn <> <> " " <> score ->
      {
        hand
        |> String.split("", trim: true)
        |> Enum.map(&amp;deck[&amp;1])
        |> valuate_hand(joker_value),
        String.to_integer(score)
      }
    end)
    |> Enum.sort_by(&amp;elem(&amp;1, 0), __MODULE__)
    |> Enum.map(&amp;elem(&amp;1, 1))
    |> Enum.with_index(1)
    |> Enum.map(fn {bid, rank} -> bid * rank end)
    |> Enum.sum()
  end

  def compare(h, h), do: :eq
  def compare({t, l}, {t, r}) when l < r, do: :lt
  def compare({t, l}, {t, r}) when l > r, do: :gt
  def compare({l, _}, {r, _}) when l < r, do: :lt
  def compare({l, _}, {r, _}) when l > r, do: :gt

  defp valuate_hand(hand, joker_value) do
    hand
    |> Enum.frequencies()
    |> Map.pop(joker_value, 0)
    |> then(fn
      {0, freq} ->
        freq

      {5, _} ->
        %{joker_value => 5}

      {j, freq} ->
        Map.update!(
          freq,
          freq |> Enum.max_by(&amp;elem(&amp;1, 1)) |> elem(0),
          &amp;(&amp;1 + j)
        )
    end)
    |> Map.values()
    |> Enum.sort()
    |> then(fn
      [5] -> 7
      [1, 4] -> 6
      [2, 3] -> 5
      [1, 1, 3] -> 4
      [1, 2, 2] -> 3
      [1, 1, 1, 2] -> 2
      _ -> 1
    end)
    |> then(fn v -> {v, hand} end)
  end
end
deck =
  ~w(2 3 4 5 6 7 8 9 T J Q K A)
  |> Enum.with_index(2)
  |> Map.new()

input
|> Kino.Input.read()
|> String.split("\n")
|> CamelCards.score(deck)
joker_value = 1
deck = Map.put(deck, "J", joker_value)

input
|> Kino.Input.read()
|> String.split("\n")
|> CamelCards.score(deck, joker_value)