From 5c04d2651e03ff2371157e0d7aae0794dd7ce100 Mon Sep 17 00:00:00 2001 From: bluepython508 Date: Sun, 10 Dec 2023 17:24:56 +0000 Subject: [PATCH] Day 10 --- lib/common.ex | 4 +++ lib/day10.ex | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/mix_tasks.ex | 1 + tests/day10/1 | 5 +++ tests/day10/1.1 | 1 + tests/day10/2 | 5 +++ tests/day10/2.1 | 1 + tests/day10/3 | 9 +++++ tests/day10/3.2 | 1 + tests/day10/4 | 10 ++++++ tests/day10/4.2 | 1 + tests/day10/5 | 10 ++++++ tests/day10/5.2 | 1 + 13 files changed, 142 insertions(+) create mode 100644 lib/day10.ex create mode 100644 tests/day10/1 create mode 100644 tests/day10/1.1 create mode 100644 tests/day10/2 create mode 100644 tests/day10/2.1 create mode 100644 tests/day10/3 create mode 100644 tests/day10/3.2 create mode 100644 tests/day10/4 create mode 100644 tests/day10/4.2 create mode 100644 tests/day10/5 create mode 100644 tests/day10/5.2 diff --git a/lib/common.ex b/lib/common.ex index 078dd7b..33d59a1 100644 --- a/lib/common.ex +++ b/lib/common.ex @@ -41,4 +41,8 @@ defmodule Aoc2023.Common do def lcm(a, b), do: div(abs(a*b), Integer.gcd(a,b)) def lcm(ls), do: ls |> Enum.reduce(&lcm/2) + + def list_map_at(l, n, f) do + List.replace_at(l, n, f.(Enum.at(l, n))) + end end diff --git a/lib/day10.ex b/lib/day10.ex new file mode 100644 index 0000000..75ffa9d --- /dev/null +++ b/lib/day10.ex @@ -0,0 +1,93 @@ +defmodule Aoc2023.Day10 do + use Aoc2023 + require Integer + + @connections %{ + ?| => [{-1, 0}, {1, 0}], + ?- => [{0, -1}, {0, 1}], + ?L => [{-1, 0}, {0, 1}], + ?J => [{-1, 0}, {0, -1}], + ?7 => [{1, 0}, {0, -1}], + ?F => [{1, 0}, {0, 1}], + ?. => [], + ?S => [] + } + + defp add_coords({y, x}, {y_, x_}), do: {y + y_, x + x_} + + defp path(s_conns, conns) do + loop = fn recur, checked, checking -> + checked_ = MapSet.union(checked, checking) + + checking_ = + checking + |> Enum.flat_map(&Map.get(conns, &1, [])) + |> MapSet.new() + |> MapSet.difference(checked_) + + if MapSet.size(checking_) > 0, do: recur.(recur, checked_, checking_), else: checked_ + end + + loop.(loop, MapSet.new(), MapSet.new(s_conns)) + end + + def parse(input) do + grid = + input + |> lines + |> Enum.map(&String.to_charlist/1) + |> Enum.with_index() + + s = + grid + |> Enum.find_value(fn {line, y} -> + x = line |> Enum.find_index(&(&1 == ?S)) + if x, do: {y, x} + end) + + conns = + grid + |> Enum.flat_map(fn {row, y} -> + row + |> Enum.with_index() + |> Enum.map(fn {c, x} -> + { + {y, x}, + Map.get(@connections, c) |> Enum.map(pipe(add_coords({y, x}))) + } + end) + end) + |> Enum.into(%{}) + + s_conns = conns |> Enum.filter(&(s in elem(&1, 1))) |> Enum.map(pipe(elem(0))) + {s, s_conns, grid, path(s_conns, conns)} + end + + def part1({_, _, _, path}) do + path + |> MapSet.size() + |> then(&(&1 / 2)) + |> trunc() + end + + def part2({{sy, sx}, s_conns, grid, path}) do + s_dirs = s_conns |> Enum.map(pipe(add_coords({-sy, -sx}))) |> Enum.sort() + s_char = @connections |> Enum.find(fn {_, conns} -> Enum.sort(conns) == s_dirs end) |> elem(0) + grid_ = grid |> list_map_at(sy, pipe(map_nth(0, pipe(List.replace_at(sx, s_char))))) + + grid_ + |> Stream.map(fn {line, y} -> + for x <- 0..length(line) - 1, reduce: {false, 0} do + {within, area} -> + cond do + {y, x} in path and Enum.at(line, x) in [?L, ?J, ?|] -> {not within, area} + {y, x} in path -> {within, area} + within -> {within, area + 1} + true -> {within, area} + end + end + |> elem(1) + end) + |> Enum.sum() + end +end diff --git a/lib/mix_tasks.ex b/lib/mix_tasks.ex index 834e38f..111cb80 100644 --- a/lib/mix_tasks.ex +++ b/lib/mix_tasks.ex @@ -11,6 +11,7 @@ defmodule Mix.Tasks.Aoc do defp module(7), do: Aoc2023.Day7 defp module(8), do: Aoc2023.Day8 defp module(9), do: Aoc2023.Day9 + defp module(10), do: Aoc2023.Day10 # [MODULE INSERTION POINT] defp base_dir(), do: System.get_env("AOC_BASE") diff --git a/tests/day10/1 b/tests/day10/1 new file mode 100644 index 0000000..689fff6 --- /dev/null +++ b/tests/day10/1 @@ -0,0 +1,5 @@ +-L|F7 +7S-7| +L|7|| +-L-J| +L|-JF diff --git a/tests/day10/1.1 b/tests/day10/1.1 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/tests/day10/1.1 @@ -0,0 +1 @@ +4 diff --git a/tests/day10/2 b/tests/day10/2 new file mode 100644 index 0000000..682499d --- /dev/null +++ b/tests/day10/2 @@ -0,0 +1,5 @@ +..F7. +.FJ|. +SJ.L7 +|F--J +LJ... diff --git a/tests/day10/2.1 b/tests/day10/2.1 new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/tests/day10/2.1 @@ -0,0 +1 @@ +8 diff --git a/tests/day10/3 b/tests/day10/3 new file mode 100644 index 0000000..bd9cdf5 --- /dev/null +++ b/tests/day10/3 @@ -0,0 +1,9 @@ +........... +.S-------7. +.|F-----7|. +.||.....||. +.||.....||. +.|L-7.F-J|. +.|..|.|..|. +.L--J.L--J. +........... diff --git a/tests/day10/3.2 b/tests/day10/3.2 new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/tests/day10/3.2 @@ -0,0 +1 @@ +4 diff --git a/tests/day10/4 b/tests/day10/4 new file mode 100644 index 0000000..adaae96 --- /dev/null +++ b/tests/day10/4 @@ -0,0 +1,10 @@ +.F----7F7F7F7F-7.... +.|F--7||||||||FJ.... +.||.FJ||||||||L7.... +FJL7L7LJLJ||LJ.L-7.. +L--J.L7...LJS7F-7L7. +....F-J..F7FJ|L7L7L7 +....L7.F7||L7|.L7L7| +.....|FJLJ|FJ|F7|.LJ +....FJL-7.||.||||... +....L---J.LJ.LJLJ... diff --git a/tests/day10/4.2 b/tests/day10/4.2 new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/tests/day10/4.2 @@ -0,0 +1 @@ +8 diff --git a/tests/day10/5 b/tests/day10/5 new file mode 100644 index 0000000..8f950ae --- /dev/null +++ b/tests/day10/5 @@ -0,0 +1,10 @@ +FF7FSF7F7F7F7F7F---7 +L|LJ||||||||||||F--J +FL-7LJLJ||||||LJL-77 +F--JF--7||LJLJ7F7FJ- +L---JF-JLJ.||-FJLJJ7 +|F|F-JF---7F7-L7L|7| +|FFJF7L7F-JF7|JL---7 +7-L-JL7||F7|L7F-7F7| +L.L7LFJ|||||FJL7||LJ +L7JLJL-JLJLJL--JLJ.L diff --git a/tests/day10/5.2 b/tests/day10/5.2 new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/tests/day10/5.2 @@ -0,0 +1 @@ +10