@@ -61,26 +61,51 @@ import Shared
6161/// Of course, the actual engine schematic is much larger. **What is the sum of
6262/// all of the part numbers in the engine schematic?**
6363///
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?**
6495///
6596@main
6697struct GearRatios : AsyncParsableCommand
6798{
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
84109}
85110
86111
@@ -95,6 +120,11 @@ struct Part
95120 var description : String { " (L: \( self . line) , C: \( self . column) " }
96121 }
97122
123+ enum Glossary : Character
124+ {
125+ case gear = " * "
126+ }
127+
98128 let character : Character
99129 let location : Location
100130 }
@@ -113,6 +143,8 @@ struct Part
113143 self . symbol = symbol
114144 self . numbers = identifiers. map ( \. number)
115145 }
146+
147+ var isGear : Bool { ( self . symbol. character == Symbol . Glossary. gear. rawValue) && ( self . numbers. count == 2 ) }
116148}
117149
118150
@@ -122,7 +154,7 @@ extension GearRatios
122154{
123155 mutating func run( ) async throws
124156 {
125- let input : AsyncLineSequence = URL . homeDirectory . appending ( path : " Desktop/input.txt " ) . lines
157+ let input : AsyncLineSequence = FileHandle . standardInput . bytes . lines
126158 let lines = try await input. reduce ( into: [ ] )
127159 {
128160 $0. append ( $1)
@@ -174,9 +206,21 @@ extension GearRatios
174206 )
175207 }
176208
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+ }
180224 }
181225}
182226
0 commit comments