# Day 16 ```elixir Mix.install([:kino_aoc]) ``` ## Section ```elixir {:ok, puzzle_input} = KinoAOC.download_puzzle("2023", "16", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION")) ``` ``` {:ok, "\\\\.......\\.............../-........|......................-......../..................../......./....|........\n\\.................\\....\\...../........|........|....../.\\....-....-..................|../...|...\\./...........\n../...-.....................\\./-.....-.........................../...........\\|......\\......--............/...\n.......|........\\...\\.........../|...../.........../...../..../...../.................\\.././..................\n...........\\|..........-.................|.|.............|.............|....|..|-...........-..-......./......\n.............................-../.......\\.........\\..........................\\.......|....|.........-.........\n..................../......................-......-...................................../...\\...........|.....\n..|..............................\\......................|....-................................................\n..........\\........./.........................|.................../....-|...../............./.....|.........//\n.-./../.................|....................|................../................\\....|..|..../|.......-./....\n................/........................\\...|.....-.....-...-........\\.............../.......-|-./...........\n.......\\|.........|..-.........................|../...../.\\.../............../.........|.....|../........\\....\n..............-./.............../...........................|....-....-..../......\\....-.......\\........./....\n...............././.-.......|/...................../..-..-..\\...\\.-.-..-................../...................\n..-......../.-.......\\..............................\\/....................................-...................\n.........................................\\....\\.........\\.-......-.|.....\\.......................\\............\n./.........\\.-.-/.............................................|/......|........-\\-............................\n-.....................|.........................|..\\..........|..--....\\..\\........./.........................\n...............\\............../............\\.........................-...............|................/....\\..\n.-.........-...........-|......../...............|.........-...-...|....................-.....................\n.\\./...............|......\\..........-..\\.................-...........................././../.-............/.-\n...-/..............-..|........................|..../.......-..........-/...............\\............../......\n|..........-\\..........\\......../.................\\.|.......-............../.......|.................../......\n.....\\...............|................/........\\.....\\..................-.../........................./.......\n..............................-..\\.../.........-..-........-.......-.............-......................|.../.\n.........../../.|.......-/-.|.|...-...............................\\\\./....|................/.\\................\n.........-..............................|.||......................./........\\..-..../.................|...../.\n.............\\...../\\.............../...-......../.....\\.....................................-/........\\..|..\\\n...............-.-../.-./....|.......\\................/...|................................................|.|\n........-.................-.........................-................\\......|.....\\......-........-...........\n|../.......|......\\............|....../..|.......|../.........................................................\n....................................../..\\....\\\\.............\\...................||/.../.../........\\.........\n............./..../....-...|........../-.............\\......................................\\/........-..-....\n.................\\\\...............|\\\\...........\\.........../......-.......-............\\..............-..-..\\\n...|..../..|../..|........./.../.-..............................\\.........-........................|.\\....||..\n......................./..|....-..............................-........................././../................\n../.\\.............//.\\.|..................-.....\\...........|..././............/...................." <> ...} ``` ```elixir # puzzle_input = ~S""" .|...\.... |.-.\..... .....|-... ........|. .......... .........\ ..../.\\.. .-.-/..|.. .|....-|.\ ..//.|.... """ ``` ``` ".|...\\....\n|.-.\\.....\n.....|-...\n........|.\n..........\n.........\\\n..../.\\\\..\n.-.-/..|..\n.|....-|.\\\n..//.|....\n" ``` ```elixir lines = String.split(puzzle_input, "\n", trim: true) map = for {line, y} <- Enum.with_index(lines), {char, x} <- line |> String.to_charlist() |> Enum.with_index(), char not in ~c".", into: %{}, do: {{y, x}, <>} {height, width} = {byte_size(hd(lines)) - 1, length(lines) - 1} ``` ``` {109, 109} ``` ```elixir defmodule Day16 do defguard in_map(yx, hw) when elem(yx, 0) in 0..elem(hw, 0) and elem(yx, 1) in 0..elem(hw, 1) def traverse(map, wh, start \\ {{0, 0}, :right}), do: do_traverse(map, wh, start, _acc = MapSet.new(), _visited = MapSet.new()) defp do_traverse(map, hw, {xy, dir} = pos, acc, visited) when in_map(xy, hw) do if pos not in visited do acc = MapSet.put(acc, xy) case Map.fetch(map, xy) do :error -> do_traverse(map, hw, next(xy, dir), acc, visited) {:ok, "|"} when dir in ~w[up down]a -> do_traverse(map, hw, next(xy, dir), acc, visited) {:ok, "-"} when dir in ~w[left right]a -> do_traverse(map, hw, next(xy, dir), acc, visited) {:ok, mirror} when mirror in ~w[/ \\] -> next = mirror(mirror, dir) do_traverse(map, hw, next(xy, next), acc, MapSet.put(visited, pos)) {:ok, "|"} when dir in ~w[left right]a -> # Add both sides to visited, as it will result in the same outcome visited = visited |> MapSet.put({xy, :left}) |> MapSet.put({xy, :right}) {acc, visited} = do_traverse(map, hw, next(xy, :up), acc, visited) do_traverse(map, hw, next(xy, :down), acc, visited) {:ok, "-"} when dir in ~w[up down]a -> # Add both sides to visited, as it will result in the same outcome visited = visited |> MapSet.put({xy, :up}) |> MapSet.put({xy, :down}) {acc, visited} = do_traverse(map, hw, next(xy, :left), acc, visited) do_traverse(map, hw, next(xy, :right), acc, visited) end else {acc, visited} end end defp do_traverse(_, _wh, _pos, acc, visited) do {acc, visited} end defp mirror("/", :up), do: :right defp mirror("/", :left), do: :down defp mirror("/", :down), do: :left defp mirror("/", :right), do: :up defp mirror("\\", :up), do: :left defp mirror("\\", :left), do: :up defp mirror("\\", :down), do: :right defp mirror("\\", :right), do: :down defp next({y, x}, :up), do: {{y - 1, x}, :up} defp next({y, x}, :left), do: {{y, x - 1}, :left} defp next({y, x}, :down), do: {{y + 1, x}, :down} defp next({y, x}, :right), do: {{y, x + 1}, :right} end ``` ``` {:module, Day16, <<70, 79, 82, 49, 0, 0, 28, ...>>, {:next, 2}} ``` ## Part 1 ```elixir {path, _} = Day16.traverse(map, {height, width}) MapSet.size(path) ``` ``` 7242 ``` ## Part 2 ```elixir start_points = Enum.concat([ Enum.flat_map(0..height, &[{{&1, 0}, :right}, {{&1, width}, :left}]), Enum.flat_map(0..width, &[{{0, &1}, :down}, {{height, &1}, :up}]) ]) start_points |> Task.async_stream(&Day16.traverse(map, {height, width}, &1)) |> Stream.map(fn {:ok, {path, _}} -> MapSet.size(path) end) |> Enum.max() ``` ``` 7572 ```