-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.swift
126 lines (99 loc) · 2.6 KB
/
Day13.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import Foundation
import Tools
final class Day13Solver: DaySolver {
let dayNumber: Int = 13
struct Input {
let program: [Int]
}
private enum Tile: Int {
case empty = 0
case wall = 1
case block = 2
case horizontalPaddle = 3
case ball = 4
}
private func printGame(with tiles: [Point2D: Tile]) {
let minX = tiles.keys.map(\.x).min()!
let minY = tiles.keys.map(\.y).min()!
let maxX = tiles.keys.map(\.x).max()!
let maxY = tiles.keys.map(\.y).max()!
for y in minY ... maxY {
var line = ""
for x in minX ... maxX {
switch tiles[.init(x: x, y: y)]! {
case .wall:
line += "+"
case .empty:
line += " "
case .block:
line += "#"
case .horizontalPaddle:
line += "="
case .ball:
line += "*"
}
}
print(line)
}
}
func solvePart1(withInput input: Input) -> Int {
let intcode = IntcodeProcessor(program: input.program)
var tiles: [Point2D: Tile] = [:]
while true {
guard
let x = intcode.continueProgramTillOutput(input: []),
let y = intcode.continueProgramTillOutput(input: []),
let tileID = intcode.continueProgramTillOutput(input: []),
let tile = Tile(rawValue: tileID)
else {
break
}
tiles[.init(x: x, y: y)] = tile
}
return tiles.values.filter { $0 == .block }.count
}
func solvePart2(withInput input: Input) -> Int {
var program = input.program
program[0] = 2 // insert 2 quarters :)
let intcode = IntcodeProcessor(program: program)
var tiles: [Point2D: Tile] = [:]
var ballPosition: Point2D = .init(x: 0, y: 0)
var paddlePosition: Point2D = .init(x: 0, y: 0)
// play game
var score = 0
while true {
let input: Int
if ballPosition.x < paddlePosition.x {
input = -1
} else if ballPosition.x > paddlePosition.x {
input = 1
} else {
input = 0
}
if let output = intcode.continueProgramTillOutput(input: [input]) {
if output == -1 {
_ = intcode.continueProgramTillOutput(input: [])!
score = intcode.continueProgramTillOutput(input: [])!
if tiles.values.filter({ $0 == .block }).isEmpty {
break
}
} else {
let x = output
let y = intcode.continueProgramTillOutput(input: [])!
let tileID = intcode.continueProgramTillOutput(input: [])!
let tile = Tile(rawValue: tileID)!
tiles[.init(x: x, y: y)] = tile
if tile == .ball {
ballPosition = .init(x: x, y: y)
} else if tile == .horizontalPaddle {
paddlePosition = .init(x: x, y: y)
}
}
}
}
return score
}
func parseInput(rawString: String) -> Input {
return .init(program: rawString.parseCommaSeparatedInts())
}
}