Advent 2023 - Day 7
Mix.install([
{:kino, "~> 0.11.3"}
])
Section
input = Kino.Input.textarea("Please paste your input file")
input =
input
|> Kino.Input.read()
|> String.split("\n")
|> Enum.map(fn line ->
[hand, bid] = String.split(line, " ")
hand = String.codepoints(hand)
bid = bid |> Integer.parse() |> elem(0)
{hand, bid}
end)
[
{["3", "2", "T", "3", "K"], 765},
{["T", "5", "5", "J", "5"], 684},
{["K", "K", "6", "7", "7"], 28},
{["K", "T", "J", "J", "T"], 220},
{["Q", "Q", "Q", "J", "A"], 483}
]
strength_of_card = fn strength_map, card ->
if strength = Map.get(strength_map, card) do
{card, strength}
else
{card, card |> Integer.parse() |> elem(0)}
end
end
#Function<41.105768164/2 in :erl_eval.expr/6>
Part 1
first_ruleset_strength_map = %{
"T" => 10,
"J" => 11,
"Q" => 12,
"K" => 13,
"A" => 14
}
%{"A" => 14, "J" => 11, "K" => 13, "Q" => 12, "T" => 10}
hands =
input
|> Enum.map(fn {hand, bid} ->
hand_freq =
hand
|> Enum.map(fn card -> card end)
|> Enum.frequencies_by(& &1)
|> Map.values()
|> Enum.sort()
|> Enum.reverse()
hand_strength =
case hand_freq do
[5] -> 7
[4, 1] -> 6
[3, 2] -> 5
[3, 1, 1] -> 4
[2, 2, 1] -> 3
[2, 1, 1, 1] -> 2
[1, 1, 1, 1, 1] -> 1
end
{hand_strength, hand, bid}
end)
[
{2, ["3", "2", "T", "3", "K"], 765},
{4, ["T", "5", "5", "J", "5"], 684},
{3, ["K", "K", "6", "7", "7"], 28},
{3, ["K", "T", "J", "J", "T"], 220},
{4, ["Q", "Q", "Q", "J", "A"], 483}
]
hands
|> Enum.sort(fn
{hand_strength, lhand, _lbid}, {hand_strength, rhand, _rbid} ->
contest =
Enum.zip(lhand, rhand)
|> Enum.find(fn
{same_card, same_card} -> false
{_not_the, _same_card} -> true
end)
if is_nil(contest) do
raise "two of the same hand???"
else
{lcard, rcard} = contest
lstrength = strength_of_card.(first_ruleset_strength_map, lcard)
rstrength = strength_of_card.(first_ruleset_strength_map, rcard)
lstrength < rstrength
end
{lhand_strength, _lhand, _lbid}, {rhand_strength, _rhand, _rbid} ->
lhand_strength <= rhand_strength
end)
|> Enum.with_index()
|> Enum.map(fn {{_hand_strength, _hand, bid}, index} ->
rank = index + 1
score = bid * rank
score
end)
|> Enum.sum()
6833
Part 2
hands =
input
|> Enum.map(fn {hand, bid} ->
{j_count, freq} =
hand
|> Enum.map(fn {card, _strength} -> card end)
|> Enum.frequencies_by(& &1)
|> Map.pop("J")
if j_count == 5 do
raise "all jokers???"
end
freq =
freq
|> Map.values()
|> Enum.sort()
|> Enum.reverse()
freq =
if is_nil(j_count) do
freq
else
freq |> List.update_at(0, &(&1 + j_count))
end
hand_strength =
case freq do
[5] -> 7
[4, 1] -> 6
[3, 2] -> 5
[3, 1, 1] -> 4
[2, 2, 1] -> 3
[2, 1, 1, 1] -> 2
[1, 1, 1, 1, 1] -> 1
end
{hand_strength, hand, bid}
end)
[
{2, [{"3", 3}, {"2", 2}, {"T", 10}, {"3", 3}, {"K", 13}], 765},
{6, [{"T", 10}, {"5", 5}, {"5", 5}, {"J", 11}, {"5", 5}], 684},
{3, [{"K", 13}, {"K", 13}, {"6", 6}, {"7", 7}, {"7", 7}], 28},
{6, [{"K", 13}, {"T", 10}, {"J", 11}, {"J", 11}, {"T", 10}], 220},
{6, [{"Q", 12}, {"Q", 12}, {"Q", 12}, {"J", 11}, {"A", 14}], 483}
]