Search code examples
algorithmscala

Advent of Code 2016: Day 1


I'm working on a coding challenge for Advent of Code. I'm fairly new to Scala and can't figure out what's wrong with my solution.

You're airdropped near Easter Bunny Headquarters in a city somewhere. "Near", unfortunately, is as close as you can get - the instructions on the Easter Bunny Recruiting Document the Elves intercepted start here, and nobody had time to work them out further.

The Document indicates that you should start at the given coordinates (where you just landed) and face North. Then, follow the provided sequence: either turn left (L) or right (R) 90 degrees, then walk forward the given number of blocks, ending at a new intersection.

There's no time to follow such ridiculous instructions on foot, though, so you take a moment and work out the destination. Given that you can only walk on the street grid of the city, how far is the shortest path to the destination?

For example:

  • Following R2, L3 leaves you 2 blocks East and 3 blocks North, or 5 blocks away.

  • R2, R2, R2 leaves you 2 blocks due South of your starting position, which is 2 blocks away.

  • R5, L5, R5, R3 leaves you 12 blocks away. How many blocks away is Easter Bunny HQ?


If you start North and look left then walk, you're going West; otherwise you're going East. Following this logic for the rest of the cardinal directions, I have come up with the following code (I've commented the first block of logic in hopes that the rest follow):

object Facing extends Enumeration {
  val North, South, East, West = Value
}

// We're at (0, 0) facing north to begin with.
// directions is a list of instructions (i.e., ((LN)|(RM))+)
val (x, y, _) = directions.foldRight((0,0, Facing.North)){(d, prev) =>
  println(s"Instruction is $d")
  val dir = d(0)
  val dist = d.substring(1).toInt
  val (x, y, looking) = prev
  println(s"x = ${x}, y = ${y}")
  println(s"Prior is = $prev")

  looking match {
    case Facing.North => {
      if(dir == 'R') {

        // If we're facing north and told to go R<dist>, we face east
        // then update the x to dist away. etc. 

        val res = (x + dist, y, Facing.East)
        println(res)
        res
      } else {
        val res = (x - dist, y, Facing.West)
        println(res)
        res
      }
    }
    case Facing.South => {
      if(dir == 'L') {
        val res = (x + dist, y, Facing.East)
        println(res)
        res
      } else {
        val res = (x - dist, y, Facing.West)
        println(res)
        res
      }
    }
    case Facing.East => {
      if(dir == 'L') {
        val res = (x, y + dist, Facing.North)
        println(res)
        res
      } else {
        val res = (x, y - dist, Facing.South)
        println(res)
        res
      }
    }
    case Facing.West => {
      if(dir == 'L') {
        val res = (x, y - dist, Facing.South)
        println(res)
        res
      } else {
        val res = (x, y + dist, Facing.North)
        println(res)
        res
      }
    }
  }
}

println(s"Distance is ${x.abs + y.abs}")

My solution is wrong (sorry that I don't have more information than that), so I must've made some logical error somewhere. I'd love some tips for how to solve this problem!


Solution

  • Your error is that you're folding right, so you apply the directions in the incorrect order. You should use foldLeft (or reverse the directions list).