DEV Community

Caleb Weeks
Caleb Weeks

Posted on

Advent of Code #10 (in Crystal)

About this time last year, we had to use a maze solving algorithm for one of the puzzles. Today's puzzle was of a similar difficulty. Part 1 wasn't all that bad. It was a little tedious, but relatively straightforward to just follow the pipes until they reached back to the start.

Part 2 involves figuring out if a point is inside out outside the loop. I used the ray casting method to count how many times a line from a given point to the edge crosses the boundary. The tricky bit here was that the ray is likely to sit directly on a boundary. Depending on if the loop bends back on itself or in the other direction, we need to determine if there is actually a crossing.

My solution isn't elegant, but it got the job done in the end. Note the two hard-coded values of the start and next pipe that I determined just by examining the input.

input = File.read("input").strip

alias Pipes = Hash(Tuple(Int32, Int32), Char)

pipes = input
  .split("\n")
  .map_with_index { |line, row| {line, row} }
  .reduce(Pipes.new) do |lines, (line, row)|
    line
      .split("")
      .map_with_index { |pipe, col| {pipe, col} }
      .reduce(Pipes.new) do |pipes, (pipe, col)|
        pipes.merge({ {row, col} => pipe })
    end.merge(lines)
end

Start = {75, 53}
Second = {75, 54}

def next_pipe(from_pos, current_pos, current_pipe)
  row = current_pos[0]
  col = current_pos[1]
  case {from_pos[0] - row, from_pos[1] - col, current_pipe}
  when {-1, 0, "L"} then {row, col + 1}
  when {-1, 0, "|"} then {row + 1, col}
  when {-1, 0, "J"} then {row, col - 1}
  when {0, 1, "F"} then {row + 1, col}
  when {0, 1, "-"} then {row, col - 1}
  when {0, 1, "L"} then {row - 1, col}
  when {1, 0, "7"} then {row, col - 1}
  when {1, 0, "|"} then {row - 1, col}
  when {1, 0, "F"} then {row, col + 1}
  when {0, -1, "J"} then {row - 1, col}
  when {0, -1, "-"} then {row, col + 1}
  when {0, -1, "7"} then {row + 1, col}  
  else {row, col}
  end
end

boundary = begin
  from = Start
  current = Second
  boundary_set = Set.new([from, current])
  while pipes[current] != "S"
    next_pipe = next_pipe(from, current, pipes[current])
    from = current
    current = next_pipe
    boundary_set.add(current)
  end
  boundary_set
end

part1 = boundary.size // 2

puts part1

part2 = pipes.keys.reduce(0) do |sum, (row, col)| 
  intersections = 0
  bend = ""
  (0..col).each do |y|
    point = {row, y}
    if boundary.includes?(point)
      case pipes[point]
      when "|"
        intersections += 1
      when "F", "L"
        bend = pipes[point]
      when "J"
        intersections += 1 if bend == "F"
        bend = ""
      when "7"
        intersections += 1 if bend == "L"
        bend = ""
      end
    end
  end
  if !boundary.includes?({row, col}) && intersections % 2 == 1
    sum + 1
  else
    sum
  end
end

puts part2
Enter fullscreen mode Exit fullscreen mode

Please leave your appreciation by commenting on this post!

It takes one minute and is worth it for your career.

Okay, let's go.

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

đź‘‹ Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay