Add Day 6 code

Day 6: Chronal Coordinates
master
Peter 7 years ago
parent f5c7fe9189
commit 36f95e6f49

@ -0,0 +1,301 @@
//
// Advent of Code 2018 "Day 6: Chronal Coordinates"
//
import Foundation
struct GridPoint: Equatable, Comparable {
var X = 0
var Y = 0
static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
return (lhs.X == rhs.X) && (lhs.Y == rhs.Y)
}
static func < (lhs: GridPoint, rhs: GridPoint) -> Bool {
return (lhs.X + lhs.Y) < (rhs.X + rhs.Y)
}
}
class Coordinates {
var points: [GridPoint] = []
var dimensions: GridPoint
init(withString str: String) {
var maxX = 0
var maxY = 0
dimensions = GridPoint(X: 0, Y: 0)
let coordStrArray = str.components(separatedBy: "\n")
for elem in coordStrArray {
let coord = elem.components(separatedBy: ", ")
guard coord.count > 1 else { return }
guard let x = Int(coord[0]), let y = Int(coord[1]) else { return }
points.append(GridPoint(X: x, Y: y))
maxX = max(maxX, x)
maxY = max(maxY, y)
}
dimensions = GridPoint(X: maxX+1, Y: maxY)
}
func distance(from: GridPoint, to: GridPoint) -> Int {
let retVal = abs(from.X - to.X) + abs(from.Y - to.Y)
return retVal
}
// Given any gridpoint, find the LocPoint with the min distance to it (returned as Int (index))
func findLocWithMinDistance(toPoint measurePt: GridPoint) -> (dist: Int, index: Int) {
var minDist = dimensions.X + dimensions.Y // max distance
var minIndex = 0
var dist: [Int: Int] = [:]
for locIndex in 0..<points.count {
dist[locIndex] = distance(from: points[locIndex], to: measurePt)
if dist[locIndex] ?? -1 < minDist {
minDist = dist[locIndex] ?? -1
minIndex = locIndex
}
}
let duplicate = dist.filter { $0.value == minDist }.count > 1
return (dist: duplicate ? -1 : minDist, index: minIndex)
}
// Given any gridpoint, find the LocPoint with the min distance to it (returned as Int (index))
func findSumOfAllDistances(toPoint measurePt: GridPoint) -> Int {
var sum = 0
for locIndex in 0..<points.count {
sum += distance(from: points[locIndex], to: measurePt)
}
return sum
}
// Fill out the grid
func fillGridWithMinDistIndicies() -> [Int] {
var retVal: [Int] = []
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let index = findLocWithMinDistance(toPoint: GridPoint(X: i, Y: j))
if index.dist < 0 {
retVal.append(-1) // indicate duplicate
} else {
retVal.append(index.index)
}
}
}
return retVal
}
// Fill out the grid
func fillGridWithSumLessThan(value nearestSum: Int) -> [Bool] {
var retVal: [Bool] = []
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
retVal.append(findSumOfAllDistances(toPoint: GridPoint(X: i, Y: j)) < nearestSum)
}
}
return retVal
}
func solveForPart1(print printMap: Bool) -> Int {
var map = fillGridWithMinDistIndicies()
var infinite: [Int : Int] = [:]
let maxX = dimensions.X
let maxY = dimensions.Y
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let idx = j * (dimensions.X + 1) + i
if i == 0 || j == 0 || i == maxX || j == maxY && infinite[idx] == nil {
infinite[map[idx]] = 1
}
if printMap {
if map[idx] < 0 {
print("..", terminator: "")
} else {
print(NSString(format:"%2d", map[idx]), terminator: "")
}
}
}
if printMap { print("") }
}
if printMap { print("infinite = \(infinite)") }
var maxArea = 0
for locIdx in 0..<points.count {
if infinite[locIdx] == nil {
let area = map.filter { $0 == locIdx }.count
maxArea = max(maxArea, area)
}
}
return maxArea
}
func solveForPart2(print printMap: Bool, withValue nearestSum: Int) -> Int {
let map = fillGridWithSumLessThan(value: nearestSum)
for j in 0...dimensions.Y {
for i in 0...dimensions.X {
let idx = j * (dimensions.X + 1) + i
if printMap {
if map[idx] {
print("#", terminator: "")
} else {
print(".", terminator: "")
}
}
}
if printMap { print("") }
}
return map.filter { $0 == true }.count
}
}
class Day06: AOCDay {
lazy var tests: (() -> ()) = day06Tests
lazy var final: (() -> ()) = day06Final
let testData = """
1, 1
1, 6
8, 3
3, 4
5, 5
8, 9
"""
func printGrid() {
let coor = Coordinates(withString: testData)
for j in 0...coor.dimensions.Y {
for i in 0...coor.dimensions.X {
if let index = coor.points.firstIndex(of: GridPoint(X: i, Y: j)) {
print(" \(index) ", terminator: "")
} else {
print(" . ", terminator: "")
}
}
print("")
}
print("")
}
func testCoordinatesInit() {
let coor = Coordinates(withString: testData)
guard coor.points.count == 6 else {
XCTAssertEqual(test: "testCoordinatesInit count", withExpression: (false))
return
}
XCTAssertEqual(test: "testCoordinatesInit A", withExpression: (coor.points[0] == GridPoint(X: 1, Y: 1)))
XCTAssertEqual(test: "testCoordinatesInit D", withExpression: (coor.points[3] == GridPoint(X: 3, Y: 4)))
XCTAssertEqual(test: "testCoordinatesInit F", withExpression: (coor.points[5] == GridPoint(X: 8, Y: 9)))
}
func testDistanceAtoAll() {
let coor = Coordinates(withString: testData)
guard coor.points.count == 6 else {
XCTAssertEqual(test: "testDistanceAtoAll count", withExpression: (false))
return
}
var dist = coor.distance(from: coor.points[0], to: coor.points[1])
XCTAssertEqual(test: "testDistanceAtoAll A to B", withExpression: (dist == 5))
dist = coor.distance(from: coor.points[0], to: coor.points[2])
XCTAssertEqual(test: "testDistanceAtoAll A to C", withExpression: (dist == 9))
dist = coor.distance(from: coor.points[0], to: coor.points[3])
XCTAssertEqual(test: "testDistanceAtoAll A to D", withExpression: (dist == 5))
dist = coor.distance(from: coor.points[0], to: coor.points[4])
XCTAssertEqual(test: "testDistanceAtoAll A to E", withExpression: (dist == 8))
dist = coor.distance(from: coor.points[0], to: coor.points[5])
XCTAssertEqual(test: "testDistanceAtoAll A to F", withExpression: (dist == 15))
}
func testFindLocWithMinDistance() {
let coor = Coordinates(withString: testData)
var nearest = coor.findLocWithMinDistance(toPoint: GridPoint(X: 0, Y: 0))
XCTAssertEqual(test: "testFindLocWithMinDistance (0, 0)", withExpression: (nearest.index == 0))
nearest = coor.findLocWithMinDistance(toPoint: GridPoint(X: 6, Y: 1))
XCTAssertEqual(test: "testFindLocWithMinDistance (6, 1)", withExpression: (nearest.index == 2))
}
func testSolveForPart1() {
let coor = Coordinates(withString: testData)
let answer = coor.solveForPart1(print: false)
XCTAssertEqual(test: "testSolveForPart1", withExpression: (answer == 17))
}
func testFindSumOfAllDistances() {
let coor = Coordinates(withString: testData)
let sum = coor.findSumOfAllDistances(toPoint: GridPoint(X: 4, Y: 3))
XCTAssertEqual(test: "testFindSumOfAllDistances (4, 3)", withExpression: (sum == 30))
}
func testSolveForPart2() {
let coor = Coordinates(withString: testData)
let answer = coor.solveForPart2(print: false , withValue: 32)
XCTAssertEqual(test: "testSolveForPart2", withExpression: (answer == 16))
}
func day06Tests() {
printGrid()
testCoordinatesInit()
testDistanceAtoAll()
testFindLocWithMinDistance()
testSolveForPart1()
testFindSumOfAllDistances()
testSolveForPart2()
}
func day06Final() {
let coor = Coordinates(withString: finalData)
var answer = coor.solveForPart1(print: false)
print("Answer to part 1 is: \(answer)")
answer = coor.solveForPart2(print: false, withValue: 10000)
print("Answer to part 2 is: \(answer)")
}
let finalData = """
342, 203
79, 64
268, 323
239, 131
246, 87
161, 93
306, 146
43, 146
57, 112
241, 277
304, 303
143, 235
253, 318
97, 103
200, 250
67, 207
345, 149
133, 222
232, 123
156, 359
80, 224
51, 145
138, 312
339, 294
297, 256
163, 311
241, 321
126, 66
145, 171
359, 184
241, 58
108, 312
117, 118
101, 180
58, 290
324, 42
141, 190
270, 149
209, 294
296, 345
68, 266
233, 281
305, 183
245, 230
161, 295
335, 352
93, 66
227, 59
264, 249
116, 173
"""
}

@ -17,6 +17,7 @@ allTests.append(Day02().tests)
allTests.append(Day03().tests)
allTests.append(Day04().tests)
allTests.append(Day05().tests)
allTests.append(Day06().tests)
// Compile list of Answers
allFinal.append(Day01().final)
@ -24,6 +25,7 @@ allFinal.append(Day02().final)
allFinal.append(Day03().final)
allFinal.append(Day04().final)
allFinal.append(Day05().final)
allFinal.append(Day06().final)
if onlyOneDay > 0 {
print("\nDay \(onlyOneDay)")

Loading…
Cancel
Save