AoC/2016/AoC2016.playground/Pages/Day 1.xcplaygroundpage/Contents.swift
2022-11-23 16:46:19 +01:00

113 lines
3.3 KiB
Swift

import Foundation
let input = """
L5, R1, R4, L5, L4, R3, R1, L1, R4, R5, L1, L3, R4, L2, L4, R2, L4, L1, R3, R1, R1, L1, R1, L5, R5, R2, L5, R2, R1, L2, L4, L4, R191, R2, R5, R1, L1, L2, R5, L2, L3, R4, L1, L1, R1, R50, L1, R1, R76, R5, R4, R2, L5, L3, L5, R2, R1, L1, R2, L3, R4, R2, L1, L1, R4, L1, L1, R185, R1, L5, L4, L5, L3, R2, R3, R1, L5, R1, L3, L2, L2, R5, L1, L1, L3, R1, R4, L2, L1, L1, L3, L4, R5, L2, R3, R5, R1, L4, R5, L3, R3, R3, R1, R1, R5, R2, L2, R5, L5, L4, R4, R3, R5, R1, L3, R1, L2, L2, R3, R4, L1, R4, L1, R4, R3, L1, L4, L1, L5, L2, R2, L1, R1, L5, L3, R4, L1, R5, L5, L5, L1, L3, R1, R5, L2, L4, L5, L1, L1, L2, R5, R5, L4, R3, L2, L1, L3, L4, L5, L5, L2, R4, R3, L5, R4, R2, R1, L5
"""
enum Direction {
case north
case east
case south
case west
func turnLeft() -> Direction {
switch self {
case .north: return .west
case .east: return .north
case .south: return .east
case .west: return .south
}
}
func turnRight() -> Direction {
switch self {
case .north: return .east
case .east: return .south
case .south: return .west
case .west: return .north
}
}
func move(units: Int) -> (north: Int, east: Int) {
switch self {
case .north: return (units, 0)
case .east: return (0, units)
case .south: return (-units, 0)
case .west: return (0, -units)
}
}
}
struct Position: Hashable {
var heading: Direction = .north
var north: Int = 0
var east: Int = 0
mutating func move(left: Bool, units: Int) -> [Position] {
heading = left ? heading.turnLeft() : heading.turnRight()
let (north, east) = heading.move(units: 1)
var result: [Position] = []
for _ in 0..<units {
self.north += north
self.east += east
result.append(self)
}
return result
}
static func == (lhs: Position, rhs: Position) -> Bool {
lhs.north == rhs.north && lhs.east == rhs.east
}
func hash(into hasher: inout Hasher) {
hasher.combine(north)
hasher.combine(east)
}
var distance: Int {
abs(north) + abs(east)
}
}
let scanner = Scanner(string: input)
extension Scanner {
func scanDirection() -> Bool {
if scanString("L") != nil { return true }
if scanString("R") != nil { return false }
fatalError("Invalid direction")
}
func scanMove() -> (Bool, Int) {
let direction = scanDirection()
guard let units = scanInt() else {
fatalError("Invalid distance")
}
guard isAtEnd || scanString(",") != nil else {
fatalError("Missing ,")
}
return (direction, units)
}
}
var position = Position()
var visited: Set<Position> = [position]
var foundPart2 = false
while !scanner.isAtEnd {
let (direction, units) = scanner.scanMove()
let path = position.move(left: direction, units: units)
for position in path {
if !foundPart2 && !visited.insert(position).inserted {
print("Part 2: Visited again: \(position.distance): \(position.north)n, \(position.east)e")
foundPart2 = true
break
}
}
}
print("Part 1:", position.distance)