-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay13.swift
More file actions
147 lines (130 loc) · 2.96 KB
/
Copy pathDay13.swift
File metadata and controls
147 lines (130 loc) · 2.96 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import AoCCommon
import Foundation
import Parsing
struct Day13: AdventDay, Sendable {
let data: String
let day = 13
let puzzleName: String = "--- Day 13: Claw Contraption ---"
init(data: String) {
self.data = data
}
var machines: [Machine] {
do {
return try MachinesParser().parse(data)
} catch {
fatalError("Unable to parse data: \(error)")
}
}
func part1() async throws -> Int {
machines.compactMap(\.costToWin).reduce(0, +)
}
func part2() async throws -> Int {
machines.map(\.corrected).compactMap((\.costToWin)).reduce(0, +)
}
}
extension Day13 {
struct Machine: Equatable {
struct Button: Equatable {
let dx: Int
let dy: Int
}
struct Prize: Equatable {
let x: Int
let y: Int
}
let buttonA: Button
let buttonB: Button
let prize: Prize
init(buttonA: Button, buttonB: Button, prize: Prize) {
self.buttonA = buttonA
self.buttonB = buttonB
self.prize = prize
}
var corrected: Machine {
let increment = 10000000000000
let NewPrize = Prize(x: prize.x + increment, y: prize.y + increment)
return Machine(buttonA: buttonA, buttonB: buttonB, prize: NewPrize)
}
var minimumCost: Int? {
var minimumCost: Int?
for a in 0 ..< 100 {
for b in 0 ..< 100 {
let currentX = a * buttonA.dx + b * buttonB.dx
let currentY = a * buttonA.dy + b * buttonB.dy
if currentX == prize.x, currentY == prize.y {
let cost = 3 * a + b
if minimumCost == nil || cost < minimumCost! {
minimumCost = cost
}
}
}
}
return minimumCost
}
}
}
extension Day13.Machine {
var costToWin: Int? {
guard let (a, b) = diophantineEEA(
ax: buttonA.dx,
bx: buttonB.dx,
ay: buttonA.dy,
by: buttonB.dy,
cx: prize.x,
cy: prize.y
)
else {
return nil
}
return 3 * a + b
}
}
extension Day13 {
struct ButtonParser: Parser {
var body: some Parser<Substring, Machine.Button> {
Parse {
"Button "
OneOf {
"A"
"B"
}
": X+"
Int.parser()
", Y+"
Int.parser()
}.map { Machine.Button(dx: $0, dy: $1) }
}
}
struct PrizeParser: Parser {
var body: some Parser<Substring, Machine.Prize> {
Parse {
"Prize: X="
Int.parser()
", Y="
Int.parser()
}.map { Machine.Prize(x: $0, y: $1) }
}
}
struct MachineParser: Parser {
var body: some Parser<Substring, Machine> {
Parse {
ButtonParser()
"\n"
ButtonParser()
"\n"
PrizeParser()
}.map { Machine(buttonA: $0, buttonB: $1, prize: $2) }
}
}
struct MachinesParser: Parser {
var body: some Parser<Substring, [Machine]> {
Many {
MachineParser()
} separator: {
"\n\n"
} terminator: {
End()
}
}
}
}