Day 7: Camel Cards
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Part 1
https://adventofcode.com/2023/day/7
data =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
sets =
data
|> Enum.map(&String.split(&1, " "))
|> Enum.map(fn [hand_str, bid_str] ->
{hand_str |> String.split("", trim: true), bid_str |> String.to_integer()}
end)
label_value =
~w(A K Q J T 9 8 7 6 5 4 3 2)
|> Enum.reverse()
|> Enum.with_index()
|> Map.new()
type_value =
~w(five_of_a_kind four_of_a_kind full_house three_of_a_kind two_pair one_pair high_card)a
|> Enum.reverse()
|> Enum.with_index()
|> Map.new()
defmodule Day07.Part1 do
def type(hand) do
hand
|> Enum.frequencies()
|> Map.values()
|> Enum.sort(:desc)
|> do_type()
end
defp do_type([5]), do: :five_of_a_kind
defp do_type([4, 1]), do: :four_of_a_kind
defp do_type([3, 2]), do: :full_house
defp do_type([3 | _]), do: :three_of_a_kind
defp do_type([2, 2 | _]), do: :two_pair
defp do_type([2 | _]), do: :one_pair
defp do_type(_), do: :high_card
end
sets
|> Enum.map(fn {hand, bid} ->
type = Day07.Part1.type(hand)
{hand, bid, type}
end)
|> Enum.sort_by(fn {labels, _bid, type} ->
label_values = labels |> Enum.map(&label_value[&1]) |> List.to_tuple()
{type_value[type], label_values}
end)
|> Enum.with_index(1)
|> Enum.map(fn {{_hand, bid, _}, rank} ->
bid * rank
end)
|> Enum.sum()
Part 2
https://adventofcode.com/2023/day/7#part2
label_value =
~w(A K Q T 9 8 7 6 5 4 3 2 J)
|> Enum.reverse()
|> Enum.with_index()
|> Map.new()
defmodule Day07.Part2 do
def type(hand) do
hand
|> Enum.frequencies()
|> Enum.sort_by(fn {_label, count} -> count end, :desc)
|> then(fn label_count_list ->
j_index = label_count_list |> Enum.find_index(fn {label, _count} -> label == "J" end)
case j_index do
nil ->
label_count_list
j_index ->
{{"J", j_count}, poped_label_count_list} = label_count_list |> List.pop_at(j_index)
case j_count do
5 ->
label_count_list
j_count ->
poped_label_count_list
|> List.update_at(0, fn {label, count} -> {label, count + j_count} end)
end
end
end)
|> Enum.map(fn {_label, count} -> count end)
|> do_type()
end
defp do_type([5]), do: :five_of_a_kind
defp do_type([4, 1]), do: :four_of_a_kind
defp do_type([3, 2]), do: :full_house
defp do_type([3 | _]), do: :three_of_a_kind
defp do_type([2, 2, 1]), do: :two_pair
defp do_type([2 | _]), do: :one_pair
defp do_type(_), do: :high_card
end
sets
|> Enum.map(fn {hand, bid} ->
type = Day07.Part2.type(hand)
{hand, bid, type}
end)
|> Enum.sort_by(fn {labels, _bid, type} ->
label_values = labels |> Enum.map(&label_value[&1]) |> List.to_tuple()
{type_value[type], label_values}
end)
|> Enum.with_index(1)
|> Enum.map(fn {{_hand, bid, _}, rank} ->
bid * rank
end)
|> Enum.sum()