@@ -61,26 +61,51 @@ import Shared
61
61
/// Of course, the actual engine schematic is much larger. **What is the sum of
62
62
/// all of the part numbers in the engine schematic?**
63
63
///
64
+ /// # Part Two
65
+ ///
66
+ /// The engineer finds the missing part and installs it in the engine! As the
67
+ /// engine springs to life, you jump in the closest gondola, finally ready to
68
+ /// ascend to the water source.
69
+ ///
70
+ /// You don't seem to be going very fast, though. Maybe something is still
71
+ /// wrong? Fortunately, the gondola has a phone labeled "help", so you pick it
72
+ /// up and the engineer answers.
73
+ ///
74
+ /// Before you can explain the situation, she suggests that you look out the
75
+ /// window. There stands the engineer, holding a phone in one hand and waving
76
+ /// with the other. You're going so slowly that you haven't even left the
77
+ /// station. You exit the gondola.
78
+ ///
79
+ /// The missing part wasn't the only issue - one of the gears in the engine is
80
+ /// wrong. A **gear** is any `*` symbol that is adjacent to **exactly two part
81
+ /// numbers**. Its **gear ratio** is the result of multiplying those two
82
+ /// numbers together.
83
+ ///
84
+ /// This time, you need to find the gear ratio of every gear and add them all
85
+ /// up so that the engineer can figure out which gear needs to be replaced.
86
+ ///
87
+ /// Consider the above engine schematic again. In this schematic, there are
88
+ /// **two** gears. The first is in the top left; it has part numbers
89
+ /// `467` and `35`, so its gear ratio is `16345`. The second gear is in the
90
+ /// lower right; its gear ratio is `451490`. (The `*` adjacent to 617 is not a
91
+ /// gear because it is only adjacent to one part number.) Adding up all of the
92
+ /// gear ratios produces **`467835`**.
93
+ ///
94
+ /// **What is the sum of all of the gear ratios in your engine schematic?**
64
95
///
65
96
@main
66
97
struct GearRatios : AsyncParsableCommand
67
98
{
68
- // /// Adds a `--mode` option to the command, which allows the command's logic
69
- // /// to branch and handle requirements of either "Part One" or "Part Two".
70
- // /// The option must be followed by a value from this enumeration.
71
- // enum Mode: String, ExpressibleByArgument, CaseIterable
72
- // {
73
- // case <#modeA#>
74
- // case <#modeB#>
75
- // }
76
- // @Option(help: "'<#modeA#>' or '<#modeB#>'")
77
- // var mode: Mode
78
-
79
- // /// Adds a flag to the command, named for the behavioral difference in
80
- // /// "Part Two." This allows the command's logic to branch and handle the
81
- // /// requirements of either "Part One" or "Part Two".
82
- // @Flag(help: "Search for both cardinal values ('one', 'two', ...) and integers.")
83
- // var <#partTwoDifference#>: Bool = false
99
+ /// Adds a "sub-command" argument to the command, which allows the logic
100
+ /// to branch and handle requirements of either "Part One" or "Part Two".
101
+ /// The argument must be a value from this enumeration.
102
+ enum Mode : String , ExpressibleByArgument , CaseIterable
103
+ {
104
+ case partNumberSum
105
+ case gearRatioSum
106
+ }
107
+
108
+ @Argument var mode : Mode
84
109
}
85
110
86
111
@@ -95,6 +120,11 @@ struct Part
95
120
var description : String { " (L: \( self . line) , C: \( self . column) " }
96
121
}
97
122
123
+ enum Glossary : Character
124
+ {
125
+ case gear = " * "
126
+ }
127
+
98
128
let character : Character
99
129
let location : Location
100
130
}
@@ -113,6 +143,8 @@ struct Part
113
143
self . symbol = symbol
114
144
self . numbers = identifiers. map ( \. number)
115
145
}
146
+
147
+ var isGear : Bool { ( self . symbol. character == Symbol . Glossary. gear. rawValue) && ( self . numbers. count == 2 ) }
116
148
}
117
149
118
150
@@ -122,7 +154,7 @@ extension GearRatios
122
154
{
123
155
mutating func run( ) async throws
124
156
{
125
- let input : AsyncLineSequence = URL . homeDirectory . appending ( path : " Desktop/input.txt " ) . lines
157
+ let input : AsyncLineSequence = FileHandle . standardInput . bytes . lines
126
158
let lines = try await input. reduce ( into: [ ] )
127
159
{
128
160
$0. append ( $1)
@@ -174,9 +206,21 @@ extension GearRatios
174
206
)
175
207
}
176
208
177
- let partNumberSum : Int = parts. flatMap ( \. numbers) . reduce ( 0 , + )
178
-
179
- print ( partNumberSum)
209
+ switch self . mode
210
+ {
211
+ case . partNumberSum:
212
+ let partNumberSum = parts. reduce ( 0 ) { $0 + $1. numbers. reduce ( 0 , + ) }
213
+ print ( partNumberSum)
214
+
215
+
216
+ case . gearRatioSum:
217
+ let gearRatioSum = parts. reduce ( 0 )
218
+ {
219
+ return if ( $1. isGear == false ) { $0 }
220
+ else { ( $0 + $1. numbers. reduce ( 1 , * ) ) }
221
+ }
222
+ print ( gearRatioSum)
223
+ }
180
224
}
181
225
}
182
226
0 commit comments