-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solution_2021_10.swift
115 lines (100 loc) · 3.03 KB
/
Solution_2021_10.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
//
// Solution_2021_10.swift
//
//
// Created by Ivan Chalov on 10.12.21.
//
import Foundation
struct Solution_2021_10: Solution {
var input: Input
func run() throws {
let input = try self.input.get()
.split(whereSeparator: \.isNewline)
.map { $0.map { Bracket(rawValue: String($0))! } }
// ------- Part 1 -------
let part1 = input.map { line in
var stack = [Bracket]()
for x in line {
if x.isOpen {
stack.append(x)
} else if let last = stack.last, x.matches(last) {
stack.removeLast()
} else {
return x.score1
}
}
return 0
}.reduce(0, +)
print(part1)
// ------- Part 2 -------
let scores = input
.compactMap { line -> [Bracket]? in
var stack = [Bracket]()
for x in line {
if x.isOpen {
stack.append(x)
} else if let last = stack.last, x.matches(last) {
stack.removeLast()
} else {
return nil
}
}
return stack
}
.map { $0.reversed().map(\.matching.score2).reduce(0) { acc, x in acc * 5 + x } }
.sorted()
let part2 = scores[scores.count / 2]
print(part2)
// ------- Test -------
assert(part1 == 469755, "WA")
assert(part2 == 2762335572, "WA")
}
}
private enum Bracket {
case open(String)
case close(String)
init?(rawValue: String) {
switch rawValue {
case "(", "[", "{", "<": self = .open(rawValue)
case ")", "]", "}", ">": self = .close(rawValue)
default: return nil
}
}
private static let openToClose = ["(" : ")", "[" : "]", "{" : "}", "<" : ">"]
private static let closeToOpen = [")" : "(", "]" : "[", "}" : "{", ">" : "<"]
var isOpen: Bool {
guard case .open = self else { return false }
return true
}
func matches(_ other: Bracket) -> Bool {
switch (other, self) {
case let (.open(b1), .close(b2)): return Self.openToClose[b1] == b2
case let (.close(b1), .open(b2)): return Self.closeToOpen[b1] == b2
default: return false
}
}
var matching: Bracket {
switch self {
case let .open(b): return .close(Self.openToClose[b]!)
case let .close(b): return .open(Self.closeToOpen[b]!)
}
}
var score1: Int {
switch self {
case .close(")"): return 3
case .close("]"): return 57
case .close("}"): return 1197
case .close(">"): return 25137
default: return 0
}
}
var score2: Int {
switch self {
case .close(")"): return 1
case .close("]"): return 2
case .close("}"): return 3
case .close(">"): return 4
default: return 0
}
}
}