Day 7
Section
defmodule D07 do
def parse_input(input) when is_binary(input) do
input
|> String.trim()
|> String.split("\n")
|> Enum.map(fn line ->
[hand, bid] = String.split(line)
{hand, String.to_integer(bid)}
end)
end
def hand_strength(hand, opts \\ []) when is_binary(hand) do
joker_rule = Keyword.get(opts, :joker_rule, false)
cards = String.graphemes(hand)
freqs = card_frequencies(cards, joker_rule)
hand_type_strength =
case freqs 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
card_strengths =
Enum.map(cards, fn
"A" -> 14
"K" -> 13
"Q" -> 12
"J" when joker_rule -> 1
"J" when not joker_rule -> 11
"T" -> 10
card -> String.to_integer(card)
end)
{hand_type_strength, card_strengths}
end
def card_frequencies(cards, _joker_rule = false) when is_list(cards) do
cards
|> Enum.frequencies()
|> Map.values()
|> Enum.sort(:desc)
end
def card_frequencies(cards, _joker_rule = true) when is_list(cards) do
groups = Enum.group_by(cards, fn x -> x end)
{groups, joker_bonus} =
if Map.has_key?(groups, "J") && map_size(groups) > 1 do
{Map.delete(groups, "J"), groups["J"] |> length()}
else
{groups, 0}
end
[highest_freq | rest] =
groups
|> Map.values()
|> Enum.map(&length/1)
|> Enum.sort(:desc)
[highest_freq + joker_bonus | rest]
end
def get_winnings(hands, opts \\ []) when is_list(hands) do
hands
|> Enum.sort_by(fn {hand, _bid} -> hand_strength(hand, opts) end)
|> Enum.with_index(1)
|> Enum.map(fn {{_hand, bid}, rank} -> bid * rank end)
|> Enum.sum()
end
def p1(hands) when is_list(hands), do: get_winnings(hands)
def p2(hands) when is_list(hands), do: get_winnings(hands, joker_rule: true)
end
{:module, D07, <<70, 79, 82, 49, 0, 0, 23, ...>>, {:p2, 1}}
ExUnit.start(autorun: false)
defmodule D07Test do
use ExUnit.Case, async: true
@test_input D07.parse_input("""
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
""")
@input Path.join(__DIR__, "inputs/d07") |> File.read!() |> D07.parse_input()
test "part 1 works" do
assert D07.p1(@test_input) == 6440
assert D07.p1(@input) == 250_453_939
end
test "part 2 works" do
assert D07.p2(@test_input) == 5905
assert D07.p2(@input) == 248_652_697
end
end
ExUnit.run()
..
Finished in 0.00 seconds (0.00s async, 0.00s sync)
2 tests, 0 failures
Randomized with seed 504885
%{total: 2, failures: 0, excluded: 0, skipped: 0}