From 36f95e6f497496e1589f42e5f252302e26f35123 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 7 Dec 2018 01:16:58 -0600 Subject: [PATCH] Add Day 6 code Day 6: Chronal Coordinates --- Sources/AOC2018/day06.swift | 301 ++++++++++++++++++++++++++++++++++++ Sources/AOC2018/main.swift | 2 + 2 files changed, 303 insertions(+) create mode 100644 Sources/AOC2018/day06.swift diff --git a/Sources/AOC2018/day06.swift b/Sources/AOC2018/day06.swift new file mode 100644 index 0000000..4b943fb --- /dev/null +++ b/Sources/AOC2018/day06.swift @@ -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.. 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.. [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.. 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 + """ +} diff --git a/Sources/AOC2018/main.swift b/Sources/AOC2018/main.swift index ef0c76e..fba28c2 100644 --- a/Sources/AOC2018/main.swift +++ b/Sources/AOC2018/main.swift @@ -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)")