Advent of Code 2017, Day 11: Hex Ed

#ruby #advent of code 2017

Part A

On Day 11 we are working with hexagonal grid which is pretty cool. I had no idea how to solve this. I was trying couple different approaches, but they didn’t work. Eventually I found this wonderful article about hexagonal grids. It is very comprehensive and interactive. To solve this puzzle we just need to learn about axial coordinates.

Actually, we don’t even need to learn all about them. We just need some information. Those coordinates are called q and r. The starting point is (0, 0).

Here is the diagram how to change them depending on the move direction:

     \ 0,-1 /
-1,0  +----+ +1,-1
     /      \
   -+ q, r   +-
     \      /
-1,+1 +----+ +1,0
     / 0,+1 \

The last thing is a function to calculate the distance between two points using axial coordinates:

function axial_distance(a, b):
    return (abs(a.q - b.q) 
          + abs(a.q + a.r - b.q - b.r)
          + abs(a.r - b.r)) / 2

Based on that we can write our solution in Ruby:

data = File.read("11.txt").split(",").map(&:strip)

q = 0
r = 0

data.each do |move|
  case move
  when "n"
    r -= 1
  when "s"
    r += 1
  when "ne"
    q += 1
    r -= 1
  when "se"
    q += 1
  when "sw"
    q -= 1
    r += 1
  when "nw"
    q -= 1
  end
end

def axial_distance(a, b)
  aq, ar = a
  bq, br = b

  ((aq - bq).abs + (aq + ar - bq - br).abs + (ar - br).abs) / 2
end

distance = axial_distance([0, 0], [q, r])

puts distance

We start with two variables q and r that are initialized with 0. Those are our initial axial coordinates. Then we apply all moves from the input file and update our coordinates. Each move is updating coordinates according to the above diagram.

At the end we calculate the distance using axial_distance method which is the implementation of the mentioned function.

Again, for more details visit hexagonal grids website. It is awesome.

Part B

The second part is just a bit different. Instead of giving the distance between the starting and ending points, we need to tell the distance between starting and the furthest point.

Here is the solution:

data = File.read("11.txt").split(",").map(&:strip)

q = 0
r = 0
max = 0

def axial_distance(a, b)
  aq, ar = a
  bq, br = b

  ((aq - bq).abs + (aq + ar - bq - br).abs + (ar - br).abs) / 2
end

data.each do |move|
  case move
  when "n"
    r -= 1
  when "s"
    r += 1
  when "ne"
    q += 1
    r -= 1
  when "se"
    q += 1
  when "sw"
    q -= 1
    r += 1
  when "nw"
    q -= 1
  end

  distance = axial_distance([0, 0], [q, r])
  max = distance if distance > max
end

puts max

This time we just need to maintain the max variable to keep the furthest point we reach.