-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay24.swift
130 lines (97 loc) · 2.54 KB
/
Day24.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
127
128
129
130
import Foundation
import Tools
final class Day24Solver: DaySolver {
let dayNumber: Int = 24
struct Input {
let ports: [Port]
}
struct Port: Hashable {
let id: UUID = .init()
let a: Int
let b: Int
let strength: Int
init(a: Int, b: Int) {
self.a = a
self.b = b
strength = a + b
}
static func == (_ lhs: Port, _ rhs: Port) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
private func bestStrength(withInput input: Int, remainingPorts: Set<Port>) -> Int {
if remainingPorts.isEmpty {
return 0
}
let availablePorts = remainingPorts.filter {
$0.a == input || $0.b == input
}
var maxStrength = 0
for availablePort in availablePorts {
let output: Int
if availablePort.a == input {
output = availablePort.b
} else {
output = availablePort.a
}
var newRemainingPorts = remainingPorts
newRemainingPorts.remove(availablePort)
maxStrength = max(
maxStrength,
availablePort.strength + bestStrength(
withInput: output,
remainingPorts: newRemainingPorts
)
)
}
return maxStrength
}
private func bestLength(withInput input: Int, remainingPorts: Set<Port>) -> (strength: Int, length: Int) {
if remainingPorts.isEmpty {
return (strength: 0, length: 0)
}
let availablePorts = remainingPorts.filter {
$0.a == input || $0.b == input
}
var maxLength = 0
var maxStrength = 0
for availablePort in availablePorts {
let output: Int
if availablePort.a == input {
output = availablePort.b
} else {
output = availablePort.a
}
var newRemainingPorts = remainingPorts
newRemainingPorts.remove(availablePort)
let result = bestLength(
withInput: output,
remainingPorts: newRemainingPorts
)
let length = 1 + result.length
let strength = availablePort.strength + result.strength
if length > maxLength {
maxLength = length
maxStrength = strength
} else if length == maxLength, strength > maxStrength {
maxStrength = strength
}
}
return (strength: maxStrength, length: maxLength)
}
func solvePart1(withInput input: Input) -> Int {
bestStrength(withInput: 0, remainingPorts: Set(input.ports))
}
func solvePart2(withInput input: Input) -> Int {
bestLength(withInput: 0, remainingPorts: Set(input.ports)).strength
}
func parseInput(rawString: String) -> Input {
return .init(ports: rawString.allLines().map { line in
let components = line.components(separatedBy: "/")
return Port(a: Int(components[0])!, b: Int(components[1])!)
})
}
}