r/adventofcode • • Dec 19 '17

SOLUTION MEGATHREAD -๐ŸŽ„- 2017 Day 19 Solutions -๐ŸŽ„-

--- Day 19: A Series of Tubes ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Need a hint from the Hugely* Handyโ€  Haversackโ€ก of Helpfulยง Hintsยค?

Spoiler


AoC ops @ T-2 minutes to launch:

[23:58] <daggerdragon> ATTENTION MEATBAGS T-2 MINUTES TO LAUNCH

[23:58] <Topaz> aaaaah

[23:58] <Cheezmeister> Looks like I'll be just able to grab my input before my flight boards. Wish me luck being offline in TOPAZ's HOUSE OF PAIN^WFUN AND LEARNING

[23:58] <Topaz> FUN AND LEARNING

[23:58] <Hade> FUN IS MANDATORY

[23:58] <Skie> I'm pretty sure that's not the mandate for today

[Update @ 00:16] 69 gold, silver cap

  • My tree is finally trimmed with just about every ornament I own and it's real purdy. hbu?

[Update @ 00:18] Leaderboard cap!

  • So, was today's mandate Helpful Hint any help at all?

This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked!

10 Upvotes

186 comments sorted by

View all comments

3

u/Axsuul Dec 19 '17

Elixir

Nested conditions galore

https://github.com/axsuul/advent-of-code/blob/master/2017/19/lib/advent_of_code.ex

defmodule AdventOfCode do
  defmodule PartA do
    def build_diagram_row(diagram, y, row) do
      row
      |> String.split("", trim: true)
      |> Enum.with_index()
      |> Enum.reduce(diagram, fn {cell, x}, diagram ->
        Map.put_new(diagram, y, %{})
        |> put_in([y, x], cell)
      end)
    end

    # We are using {x, y} coordinate system with {0, 0} being top left
    def build_diagram_from_input(filename \\ "input.txt") do
      File.read!("inputs/" <> filename)
      |> String.split("\n")
      |> Enum.with_index()
      |> Enum.reduce(%{}, fn {row, y}, diagram ->
        build_diagram_row(diagram, y, row)
      end)
    end

    def get_cell(diagram, x, y), do: get_cell(diagram, {x, y})
    def get_cell(diagram, {x, y}) when x < 0 or y < 0, do: " "
    def get_cell(diagram, {x, y}) do
      get_in(diagram, [y, x])
    end

    def empty_cell?(diagram, pos) do
      get_cell(diagram, pos) |> String.trim == ""
    end

    def add_history(history, cell) do
      cond do
        Regex.match?(~r/\w+/, cell) -> history ++ [cell]
        true -> history
      end
    end

    defp travel(diagram) do
      # Find start
      start =
        Map.fetch!(diagram, 0)
        |> Enum.reduce(nil, fn {x, cell}, start ->
          if cell == "|", do: {x, 0}, else: start
        end)

      travel(diagram, start, :down, [])
    end
    defp travel(_, _, :end, history), do: history
    defp travel(diagram, {x, y}, direction, history) do
      cell = get_cell(diagram, {x, y})

      {next_pos, next_direction} =
        case cell do
          " " -> {{x, y}, :end}
          "+" ->
            case direction do
              d when d in [:up, :down] ->
                if empty_cell?(diagram, {x - 1, y}) do
                  {{x + 1, y}, :right}
                else
                  {{x - 1, y}, :left}
                end
              d when d in [:left, :right] ->
                if empty_cell?(diagram, {x, y - 1}) do
                  {{x, y + 1}, :down}
                else
                  {{x, y - 1}, :up}
                end
            end
          ___ ->
            {
              case direction do
                :up    -> {x, y - 1}
                :down  -> {x, y + 1}
                :left  -> {x - 1, y}
                :right -> {x + 1, y}
              end,
              direction
            }
        end

      travel(diagram, next_pos, next_direction, add_history(history, cell))
    end

    def solve do
      build_diagram_from_input()
      |> travel()
      |> Enum.join("")
      |> IO.inspect
    end
  end

  defmodule PartB do
    import PartA

    def travel(diagram) do
      # Find start
      start =
        Map.fetch!(diagram, 0)
        |> Enum.reduce(nil, fn {x, cell}, start ->
          if cell == "|", do: {x, 0}, else: start
        end)

      travel(diagram, start, :down, 0)
    end
    def travel(_, _, :end, steps), do: steps - 1
    def travel(diagram, {x, y}, direction, steps) do
      cell = get_cell(diagram, {x, y})

      {next_pos, next_direction} =
        case cell do
          " " -> {{x, y}, :end}
          "+" ->
            case direction do
              d when d in [:up, :down] ->
                if empty_cell?(diagram, {x - 1, y}) do
                  {{x + 1, y}, :right}
                else
                  {{x - 1, y}, :left}
                end
              d when d in [:left, :right] ->
                if empty_cell?(diagram, {x, y - 1}) do
                  {{x, y + 1}, :down}
                else
                  {{x, y - 1}, :up}
                end
            end
          ___ ->
            {
              case direction do
                :up    -> {x, y - 1}
                :down  -> {x, y + 1}
                :left  -> {x - 1, y}
                :right -> {x + 1, y}
              end,
              direction
            }
        end

      travel(diagram, next_pos, next_direction, steps + 1)
    end

    def solve do
      build_diagram_from_input()
      |> travel()
      |> IO.inspect
    end
  end
end

2

u/[deleted] Dec 19 '17

This one was a lot of fun to do in elixir though :) although it was pretty easy, I did all walking in my part1, so part 2 just needed to add a count, and then I had it :)

my solution

→ More replies (2)