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)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue