Created
December 14, 2016 20:31
-
-
Save DeepFriedTwinkie/ba5bb6032e9959eadf7ae1aa056525f0 to your computer and use it in GitHub Desktop.
AdventOfCode.com 2016 Day 1 Solution (http://adventofcode.com/2016/day/1) (Part 2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
enum Axis { | |
case X | |
case Y | |
} | |
enum Instruction { | |
case left (distance:Int) | |
case right (distance:Int) | |
init?(instructionString:String) { | |
guard instructionString.characters.count >= 2 else { return nil } | |
let firstIndex = instructionString.index(after: instructionString.startIndex) | |
let direction = instructionString.substring(to: firstIndex).uppercased() | |
let distance = instructionString.substring(from: firstIndex) | |
guard let distanceInt = Int(distance), distanceInt > 0 else { return nil } | |
switch direction { | |
case "R": | |
self = .right(distance: distanceInt) | |
case "L": | |
self = .left(distance: distanceInt) | |
default: | |
return nil | |
} | |
} | |
var distance: Int { | |
get { | |
switch self { | |
case let .left(dist): return dist | |
case let .right(dist): return dist | |
} | |
} | |
} | |
} | |
enum Direction { | |
case North | |
case South | |
case East | |
case West | |
func turn(instruction:Instruction) -> Direction { | |
if case .left(_) = instruction { | |
switch self { | |
case .North: return .West | |
case .South: return .East | |
case .East: return .North | |
case .West: return .South | |
} | |
} else { | |
switch self { | |
case .North: return .East | |
case .South: return .West | |
case .East: return .South | |
case .West: return .North | |
} | |
} | |
} | |
var axisMultiplier: (Axis, Int) { | |
get { | |
switch self { | |
case .North: return (.X, 1) | |
case .South: return (.X, -1) | |
case .East: return (.Y, 1) | |
case .West: return (.Y, -1) | |
} | |
} | |
} | |
} | |
struct Location{ | |
let x: Int | |
let y: Int | |
let direction: Direction | |
} | |
// Implement Hashable so that Locations can be stored in a Set | |
extension Location: Hashable, Equatable { | |
public var hashValue: Int { | |
return x^y | |
} | |
} | |
func ==(lhs: Location, rhs: Location) -> Bool { | |
return lhs.x == rhs.x && lhs.y == rhs.y | |
} | |
// Day 1: | |
let inputString = "R5, L2, L1, R1, R3, R3, L3, R3, R4, L2, R4, L4, R4, R3, L2, L1, L1, R2, R4, R4, L4, R3, L2, R1, L4, R1, R3, L5, L4, L5, R3, L3, L1, L1, R4, R2, R2, L1, L4, R191, R5, L2, R46, R3, L1, R74, L2, R2, R187, R3, R4, R1, L4, L4, L2, R4, L5, R4, R3, L2, L1, R3, R3, R3, R1, R1, L4, R4, R1, R5, R2, R1, R3, L4, L2, L2, R1, L3, R1, R3, L5, L3, R5, R3, R4, L1, R3, R2, R1, R2, L4, L1, L1, R3, L3, R4, L2, L4, L5, L5, L4, R2, R5, L4, R4, L2, R3, L4, L3, L5, R5, L4, L2, R3, R5, R5, L1, L4, R3, L1, R2, L5, L1, R4, L1, R5, R1, L4, L4, L4, R4, R3, L5, R1, L3, R4, R3, L2, L1, R1, R2, R2, R2, L1, L1, L2, L5, L3, L1" | |
let inputs = inputString.components(separatedBy: ", ") | |
let instructions = inputs.flatMap { (insString) -> Instruction? in | |
return Instruction(instructionString: insString) | |
} | |
// Just move one step in a certain direction | |
func performStep(direction:Direction, currentLocation:Location) -> Location { | |
let axisMultiplier = direction.axisMultiplier | |
let distanceOffset = axisMultiplier.1 | |
if axisMultiplier.0 == .Y { | |
return Location(x: currentLocation.x, y: currentLocation.y + distanceOffset, direction: direction) | |
} else { | |
return Location(x: currentLocation.x + distanceOffset, y: currentLocation.y, direction: direction) | |
} | |
} | |
var currentLocation = Location(x: 0, y: 0, direction: .North) | |
var visitedLocations:Set = [currentLocation] // Saves all of the unique locations that have been visisted | |
loopThroughInstructions: for instruction in instructions { | |
let direction = currentLocation.direction.turn(instruction: instruction) | |
for _ in 1...instruction.distance { | |
currentLocation = performStep(direction: direction, currentLocation: currentLocation) | |
if visitedLocations.contains(currentLocation) { | |
break loopThroughInstructions // We've found the current location in our list of visited places, so this is the answer | |
} else { | |
visitedLocations.insert(currentLocation) // We haven't been here before, record that we have | |
} | |
} | |
} | |
let distance = abs(currentLocation.x) + abs(currentLocation.y) | |
print("Distance: \(distance)") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment