AoC 2023 - Day 07
Mix.install([
{:kino, "~> 0.11.3"}
])
Section
input_e1 =
"day07-e1.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
input =
"day07.txt"
|> Kino.FS.file_path()
|> File.read!()
|> String.trim()
[input_e1, input]
defmodule Solution do
@cards ~w(2 3 4 5 6 7 8 9 T J Q K A)
|> Enum.with_index(2)
|> Enum.reduce(%{}, fn {v, k}, a -> Map.put(a, v, k) end)
def part_1(input) do
input
|> String.split("\n")
|> Enum.map(&parse_line/1)
|> Enum.sort(&sort/2)
|> Enum.with_index(1)
|> Enum.map(fn {{_cards, _hand, bid}, k} ->
k * bid
end)
|> Enum.sum()
end
def part_2(input) do
input
|> String.split("\n")
|> Enum.map(&parse_line_2/1)
|> Enum.sort(&sort/2)
|> IO.inspect()
|> Enum.with_index(1)
|> Enum.map(fn {{_cards, _hand, bid}, k} ->
k * bid
end)
|> Enum.sum()
end
def sort(
{[a1, b1, c1, d1, e1], rank_1, _},
{[a2, b2, c2, d2, e2], rank_2, _}
) do
cond do
rank_1 < rank_2 ->
true
rank_1 == rank_2 and a1 < a2 ->
true
rank_1 == rank_2 and a1 == a2 and b1 < b2 ->
true
rank_1 == rank_2 and a1 == a2 and b1 == b2 and c1 < c2 ->
true
rank_1 == rank_2 and a1 == a2 and b1 == b2 and c1 == c2 and d1 < d2 ->
true
rank_1 == rank_2 and a1 == a2 and b1 == b2 and c1 == c2 and d1 == d2 and e1 < e2 ->
true
true ->
false
end
end
defp parse_line(input) do
[cards, bids] = String.split(input, " ")
cards = cards |> String.codepoints() |> Enum.map(&to_card/1)
{cards, rank_hand(cards), String.to_integer(bids)}
end
defp parse_line_2(input) do
[cards, bids] = String.split(input, " ")
cards = cards |> String.codepoints() |> Enum.map(&to_card_2/1)
{cards, rank_hand_with_joker(cards), String.to_integer(bids)}
end
def to_card(card), do: Map.get(@cards, card)
def to_card_2("J"), do: 1
def to_card_2(card), do: to_card(card)
def rank_hand(hand), do: hand |> Enum.frequencies() |> Map.values() |> Enum.sort() |> rank()
def rank_hand_with_joker(hand) do
rank = rank_hand(hand)
wild = hand |> Enum.frequencies() |> Map.get(1)
case {rank, wild} do
{_, nil} -> rank
# [1, 1, 1, 1, 1] -> [1, 1, 1, 2]
{1, _} -> 2
# [1, 1, 1, 2] -> [1, 1, 3]
{2, _} -> 4
# [1, 2, 2] -> [1, 3]
{3, 1} -> 5
# [1, 2, 2] -> [1, 4] if 2J
{3, 2} -> 6
# [1, 1, 3] -> [1, 4]
{4, _} -> 6
# [2, 3] - both can be J
{5, _} -> 7
{6, _} -> 7
{7, _} -> rank
end
end
def rank([1, 1, 1, 1, 1]), do: 1
def rank([1, 1, 1, 2]), do: 2
def rank([1, 2, 2]), do: 3
def rank([1, 1, 3]), do: 4
def rank([2, 3]), do: 5
def rank([1, 4]), do: 6
def rank([5]), do: 7
end
Solution.part_1(input)
Solution.part_2(input)