diff --git a/day3.livemd b/day3.livemd new file mode 100644 index 0000000..fd17974 --- /dev/null +++ b/day3.livemd @@ -0,0 +1,136 @@ +# AOC 2022 - Day 3 + +```elixir +Mix.install([ + {:req, "~> 0.3.3"} +]) +``` + +## Puzzle description + +[Day 3: Rucksack Reorganization](https://adventofcode.com/2022/day/3). + +## Input + +```elixir +defmodule Load do + def input do + aoc_session = System.fetch_env!("LB_AOC_SESSION") + input_url = "https://adventofcode.com/2022/day/3/input" + Req.get!(input_url, headers: [cookie: "session=#{aoc_session}"]).body + end +end +``` + +```elixir +defmodule A do + def intersection(str1, str2) do + str1_set = MapSet.new(String.graphemes(str1)) + str2_set = MapSet.new(String.graphemes(str2)) + MapSet.intersection(str1_set, str2_set) + end +end + +A.intersection("hello", "world") +``` + +## Solution + +```elixir +defmodule Util do + @items String.split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", "", trim: true) + + def value_of(item) do + Enum.find_index(@items, fn c -> c == item end) + 1 + end + + def process(input) do + input + |> String.trim() + |> String.split("\n", trim: true) + end + + def intersection(str1, str2) do + str1_set = MapSet.new(String.graphemes(str1)) + str2_set = MapSet.new(String.graphemes(str2)) + MapSet.intersection(str1_set, str2_set) + end + + def intersection(str1, str2, str3) do + str1_set = MapSet.new(String.graphemes(str1)) + str2_set = MapSet.new(String.graphemes(str2)) + str3_set = MapSet.new(String.graphemes(str3)) + intersection = MapSet.intersection(str1_set, str2_set) + MapSet.intersection(intersection, str3_set) + end +end +``` + +```elixir +defmodule Part1 do + def run(input) do + input + |> Util.process() + |> Enum.map(&String.split_at(&1, div(String.length(&1), 2))) + |> Enum.reduce(0, fn {first, second}, acc -> + priority = + Util.intersection(first, second) + |> MapSet.to_list() + |> List.first() + |> Util.value_of() + + acc + priority + end) + end +end + +defmodule Part2 do + def run(input) do + input + |> Util.process() + |> Enum.chunk_every(3) + |> Enum.map(fn [items1, items2, items3] -> + Util.intersection(items1, items2, items3) + |> MapSet.to_list() + |> List.first() + |> Util.value_of() + end) + |> Enum.reduce(&+/2) + end +end + +ExUnit.start(autorun: false) + +defmodule Test do + use ExUnit.Case, async: true + @example_input ~s(vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw) + @input Load.input() + + test "it loads the input" do + assert String.length(@input) > 0 + end + + test "part 1 example" do + assert Part1.run(@example_input) === 157 + end + + test "part 1" do + assert Part1.run(@input) === 8105 + end + + test "part 2 example" do + assert Part2.run(@example_input) === 70 + end + + test "part 2" do + assert Part2.run(@input) === 0 + end +end + +ExUnit.run() +```