diff --git a/lib/day7.ex b/lib/day7.ex index 3685dbd..21bc73c 100644 --- a/lib/day7.ex +++ b/lib/day7.ex @@ -1,7 +1,46 @@ defmodule Aoc2023.Day7 do use Aoc2023 - @ranking_1 %{ + def hand_type(values) do + values + |> Enum.frequencies() + |> then(fn freq -> + {jokers, freq_} = freq |> Map.pop(0, 0) + common = freq_ |> Enum.max_by(pipe(elem(1))) |> elem(0) + freq_ |> Map.update!(common, &(&1 + jokers)) + end) + |> Enum.map(pipe(elem(1))) + |> Enum.sort(:desc) + |> case do + [5] -> 6 + [4, 1] -> 5 + [3, 2] -> 4 + [3, 1, 1] -> 3 + [2, 2, 1] -> 2 + [2, 1, 1, 1] -> 1 + [1, 1, 1, 1, 1] -> 0 + end + end + + def parse(input) do + fn rankings -> + input + |> lines + |> Enum.map(&String.split/1) + |> Enum.map(fn [hand, bid] -> + { + hand |> String.to_charlist() |> Enum.map(&Map.get(rankings, &1)), + bid |> String.to_integer() + } + end) + |> Enum.sort_by(elem(0) |> hand_type &&& elem(0), :asc) + |> Enum.with_index(1) + |> Enum.map(fn {{_, bid}, index} -> bid * index end) + |> Enum.sum() + end + end + + @ranking %{ ?A => 13, ?K => 12, ?Q => 11, @@ -17,57 +56,11 @@ defmodule Aoc2023.Day7 do ?2 => 1 } - @ranking_2 @ranking_1 |> Map.put(?J, 0) - - def hand_type(values) do - for ty <- values, reduce: %{} do - m -> Map.update(m, ty, 1, &(&1 + 1)) - end - |> Enum.map(pipe(elem(1))) - |> Enum.sort(:desc) - |> case do - [5] -> 6 - [4, 1] -> 5 - [3, 2] -> 4 - [3, 1, 1] -> 3 - [2, 2, 1] -> 2 - [2, 1, 1, 1] -> 1 - [1, 1, 1, 1, 1] -> 0 - end - end - - def parse(input) do - fn rankings, hand_rank -> - input - |> lines - |> Enum.map(&String.split/1) - |> Enum.map(fn [hand, bid] -> - { - hand |> String.to_charlist() |> Enum.map(&Map.get(rankings, &1)), - bid |> String.to_integer() - } - end) - |> Enum.sort_by(elem(0) |> hand_rank.() &&& elem(0), :asc) - |> Enum.with_index(1) - |> Enum.map(fn {{_, bid}, index} -> bid * index end) - |> Enum.sum() - end - end - def part1(input) do - input.(@ranking_1, &hand_type/1) + input.(@ranking) end def part2(input) do - input.( - @ranking_2, - fn hand -> - @ranking_2 - |> Enum.map(pipe(elem(1))) - |> Enum.map(fn j -> hand |> Enum.map(&if &1 == 0, do: j, else: &1) end) - |> Enum.map(&hand_type/1) - |> Enum.max() - end - ) + input.(@ranking |> Map.put(?J, 0)) end end