Skip to content

Instantly share code, notes, and snippets.

@samisuteria
Created March 30, 2020 03:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samisuteria/e229ae7c4cf3396162295f35cc85da91 to your computer and use it in GitHub Desktop.
Save samisuteria/e229ae7c4cf3396162295f35cc85da91 to your computer and use it in GitHub Desktop.
import Foundation
struct Point: Equatable, CustomStringConvertible {
let x: Int
let y: Int
init(_ x: Int, _ y: Int) {
self.x = x
self.y = y
}
var description: String { "(\(x), \(y))" }
static func + (_ lhs: Point, _ rhs: Point) -> Point {
Point(lhs.x + rhs.x, lhs.y + rhs.y)
}
static func - (_ lhs: Point, _ rhs: Point) -> Point {
Point(lhs.x - rhs.x, lhs.y - rhs.y)
}
static var zero: Point { Point(0,0) }
}
enum Direction: String {
case N, S, E, W, NE, NW, SE, SW
var delta: Point {
switch self {
case .N: return Point(0, 1)
case .S: return Point(0, -1)
case .E: return Point(1, 0)
case .W: return Point(-1, 0)
case .NE: return Direction.N.delta + Direction.E.delta
case .NW: return Direction.N.delta + Direction.W.delta
case .SE: return Direction.S.delta + Direction.E.delta
case .SW: return Direction.S.delta + Direction.W.delta
}
}
}
struct Rule: CustomStringConvertible {
let destination: String
let direction: Direction
let source: String
init?(string: String) {
let values = string
.split(separator: " ")
.map { String($0) }
guard
values.count == 3,
let parsedDirection = Direction(rawValue: values[1])
else { return nil }
self.destination = values[0]
self.direction = parsedDirection
self.source = values[2]
}
var description: String { "\(destination) \(direction) \(source)" }
}
//let input = """
//A NW B
//A N B
//"""
let input = """
A N B
B NE C
C N A
"""
func isValidRules(input: String) -> Bool {
let parsedRules: [Rule] = input
.split(separator: "\n")
.map { String($0) }
.compactMap { Rule(string: $0) }
var pointsOnMap = Set<String>()
var locationsOfPoints = Dictionary<String, Point>()
var isValid = true
for rule in parsedRules {
print(rule)
switch (pointsOnMap.contains(rule.source), pointsOnMap.contains(rule.destination)) {
case (false, false):
print("neither point is on map, adding them")
pointsOnMap.insert(rule.source)
locationsOfPoints[rule.source] = .zero
pointsOnMap.insert(rule.destination)
locationsOfPoints[rule.destination] = .zero + rule.direction.delta
case (true, false):
if let sourcePoint = locationsOfPoints[rule.source] {
print("source on map, adding destination")
pointsOnMap.insert(rule.destination)
locationsOfPoints[rule.destination] = sourcePoint + rule.direction.delta
}
case (false, true):
if let destinationPoint = locationsOfPoints[rule.destination] {
print("destination on map, adding source by inverting direction")
pointsOnMap.insert(rule.source)
locationsOfPoints[rule.source] = destinationPoint - rule.direction.delta
}
case (true, true):
print("both points already on map, going to rules check")
}
print(pointsOnMap)
print(locationsOfPoints)
guard
let sourcePoint = locationsOfPoints[rule.source],
let destinationPoint = locationsOfPoints[rule.destination]
else { continue }
switch rule.direction {
case .N, .S:
if sourcePoint.y + rule.direction.delta.y != destinationPoint.y {
isValid = false
}
case .E, .W:
if sourcePoint.x + rule.direction.delta.x != destinationPoint.x {
isValid = false
}
default:
if sourcePoint + rule.direction.delta != destinationPoint {
isValid = false
}
}
print("valid: \(isValid)")
}
return isValid
}
isValidRules(input: input)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment