Add code for Day 9

Day 9: Marble Mania
master
Peter 7 years ago
parent 96d9683eb2
commit cb807de984

@ -0,0 +1,187 @@
//
// Advent of Code 2018 "Day 9: Marble Mania"
//
import Foundation
struct List {
var val = 0
var ptrNext = -1
var ptrPrev = -1
}
class Marble {
var player: [Int] = []
var lastMarble = 0
var circle: [List] = []
var circleCount = 1
var currentMarble = 0
var currentPlayer = 0
var PC = 0
init(numPlayers: Int, lastMarble last: Int) {
circle = Array(repeating: List(), count: last+1)
circleCount = 1
currentMarble = 0
currentPlayer = 0
PC = 0
circle[0].ptrNext = 0
circle[0].ptrPrev = 0
player = Array(repeating: 0, count: numPlayers)
for num in 0...last { circle[num].val = num }
lastMarble = last
}
func insert() {
circle[currentMarble].ptrNext = circle[PC].val
circle[currentMarble].ptrPrev = circle[PC].ptrPrev
circle[circle[PC].ptrPrev].ptrNext = circle[currentMarble].val
circle[PC].ptrPrev = circle[currentMarble].val
PC = currentMarble
circleCount += 1
}
func remove() {
circle[circle[PC].ptrPrev].ptrNext = circle[PC].ptrNext
circle[circle[PC].ptrNext].ptrPrev = circle[PC].ptrPrev
PC = circle[circle[PC].ptrPrev].ptrNext
circleCount -= 1
}
func incrPC() {
PC = circle[PC].ptrNext
}
func incrPC(by n: Int) {
for _ in 0..<n { incrPC() }
}
func decrPC() {
PC = circle[PC].ptrPrev
}
func decrPC(by n: Int) {
for _ in 0..<n { decrPC() }
}
func incrPlayer() {
currentPlayer += 1
if currentPlayer == player.count { currentPlayer = 0 }
}
func placeNextMarble() {
currentMarble += 1
if currentMarble % 23 == 0 {
player[currentPlayer] += currentMarble
decrPC(by: 7)
player[currentPlayer] += circle[PC].val
remove()
} else {
incrPC(by: 2)
insert()
}
incrPlayer()
}
}
class Day09: AOCDay {
lazy var tests: (() -> ()) = day09Tests
lazy var final: (() -> ()) = day09Final
let testData: [(Int, Int, Int)] = [
(9, 25, 32),
(13, 7999, 146373),
(17, 1104, 2764),
(21, 6111, 54718),
(30, 5807, 37305)
]
let finalData = (477, 70851)
func printCircle(circle: [List], withCount circleCount: Int) -> String {
var retVal = ""
var marble = circle[0]
for _ in 0..<circleCount {
retVal += "\(marble.val), "
marble = circle[marble.ptrNext]
}
return retVal
}
func testMarbleInit() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testMarbleInit num", withExpression: (marb.player.count == 9))
XCTAssertEqual(test: "testMarbleInit last", withExpression: (marb.lastMarble == 15))
XCTAssertEqual(test: "testMarbleInit result", withExpression: (result == "0, "))
}
func testInsert() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
for _ in 0...3 {
marb.currentMarble += 1
marb.insert()
marb.incrPC(by:2)
}
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testInsert result", withExpression: (result == "0, 4, 2, 1, 3, "))
}
func testRemove() {
let marb = Marble(numPlayers: 9, lastMarble: 15)
for _ in 0...3 {
marb.currentMarble += 1
marb.insert()
marb.incrPC(by:2)
}
marb.decrPC(by: 2)
marb.remove()
let result = printCircle(circle: marb.circle, withCount: marb.circleCount)
XCTAssertEqual(test: "testRemove result", withExpression: (result == "0, 2, 1, 3, "))
}
func testPlaceNextMarble() {
var result = ""
for data in testData {
let marb = Marble(numPlayers: data.0, lastMarble: data.1)
for _ in 0..<marb.lastMarble {
marb.placeNextMarble()
if data == (9, 25, 32) {
result = printCircle(circle: marb.circle, withCount: marb.circleCount)
}
}
let max = marb.player.max() ?? 0
if data == (9, 25, 32) {
XCTAssertEqual(test: "testPlaceMarble result", withExpression: (result == "0, 16, 8, 17, 4, 18, 19, 2, 24, 20, 25, 10, 21, 5, 22, 11, 1, 12, 6, 13, 3, 14, 7, 15, "))
}
XCTAssertEqual(test: "testPlaceMarble \(data)", withExpression: (max == data.2))
}
}
func day09Tests() {
testMarbleInit()
testInsert()
testRemove()
testPlaceNextMarble()
}
func day09Final() {
var marb = Marble(numPlayers: 477, lastMarble: 70851)
for _ in 0..<marb.lastMarble {
marb.placeNextMarble()
}
var max = marb.player.max() ?? 0
print("Answer to part 1 is: \(max)")
marb = Marble(numPlayers: 477, lastMarble: 7085100)
for i in 0..<marb.lastMarble {
marb.placeNextMarble()
if i % 1000000 == 0 { print("\(i)")}
}
max = marb.player.max() ?? 0
print("Answer to part 2 is: \(max)")
}
}

@ -20,6 +20,7 @@ allTests.append(Day05().tests)
allTests.append(Day06().tests)
allTests.append(Day07().tests)
allTests.append(Day08().tests)
allTests.append(Day09().tests)
// Compile list of Answers
allFinal.append(Day01().final)
@ -30,6 +31,7 @@ allFinal.append(Day05().final)
allFinal.append(Day06().final)
allFinal.append(Day07().final)
allFinal.append(Day08().final)
allFinal.append(Day09().final)
if onlyOneDay > 0 {
print("\nDay \(onlyOneDay)")

Loading…
Cancel
Save