Skip to content

Commit 614d3b9

Browse files
author
Matthew Judy
committed
Part one solved for 2023-03.
1 parent 96c2a93 commit 614d3b9

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

Sources/2023/03/GearRatios.swift

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ 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+
///
6465
@main
6566
struct GearRatios: AsyncParsableCommand
6667
{
@@ -83,14 +84,99 @@ struct GearRatios: AsyncParsableCommand
8384
}
8485

8586

87+
struct Part
88+
{
89+
struct Symbol
90+
{
91+
struct Location: Equatable, CustomStringConvertible
92+
{
93+
let line : Int
94+
let column : Int
95+
var description : String { "(L:\(self.line), C:\(self.column)" }
96+
}
97+
98+
let character : Character
99+
let location : Location
100+
}
101+
102+
struct Identifier
103+
{
104+
let number : Int
105+
let border : [Symbol.Location]
106+
}
107+
108+
let symbol : Symbol
109+
let numbers : [Int]
110+
111+
init(symbol: Symbol, identifiers: [Identifier])
112+
{
113+
self.symbol = symbol
114+
self.numbers = identifiers.map(\.number)
115+
}
116+
}
117+
118+
86119
// MARK: - Command Execution
87120

88121
extension GearRatios
89122
{
90123
mutating func run() async throws
91124
{
92-
let input: AsyncLineSequence = FileHandle.standardInput.bytes.lines // URL.homeDirectory.appending(path: "Desktop/input.txt").lines
93-
try await input.reduce(into: []) { $0.append($1) }.forEach { print($0) }
125+
let input: AsyncLineSequence = URL.homeDirectory.appending(path: "Desktop/input.txt").lines
126+
let lines = try await input.reduce(into: [])
127+
{
128+
$0.append($1)
129+
}
130+
131+
typealias FoundTokens = (symbols: [Part.Symbol], identifiers: [Part.Identifier])
132+
133+
let (symbols, identifiers) : FoundTokens = lines.enumerated().reduce(into: FoundTokens([], []))
134+
{
135+
foundTokens, lineIndexAndline in let (lineIndex, line) = lineIndexAndline
136+
137+
// Find symbols in line.
138+
line.ranges(of: /[^\d\.]/).forEach
139+
{
140+
symbolRange in
141+
142+
let symbolIndex : Int = line.distance(from: line.startIndex, to: symbolRange.lowerBound)
143+
144+
foundTokens.symbols.append(Part.Symbol(character: line[symbolRange].first!, location: Part.Symbol.Location(line: lineIndex, column: symbolIndex)))
145+
}
146+
147+
// Find identifiers (integers) in line, and the border around them.
148+
line.ranges(of: /\d+/).forEach
149+
{
150+
idRange in
151+
152+
let idStartIndex : Int = line.distance(from: line.startIndex, to: idRange.lowerBound)
153+
let idEndIndex : Int = line.distance(from: line.startIndex, to: idRange.upperBound)
154+
let borderRange : ClosedRange<Int> = ((idStartIndex - 1)...idEndIndex).clamped(to: (0...(line.count - 1)))
155+
156+
let startLocation = Part.Symbol.Location(line: lineIndex, column: borderRange.lowerBound)
157+
let endLocation = Part.Symbol.Location(line: lineIndex, column: borderRange.upperBound)
158+
let aboveLocations : [Part.Symbol.Location] = borderRange.map { .init(line: (lineIndex - 1), column: $0) }
159+
let belowLocations : [Part.Symbol.Location] = borderRange.map { .init(line: (lineIndex + 1), column: $0) }
160+
let borderLocations : [Part.Symbol.Location] = ( [startLocation, endLocation] + aboveLocations + belowLocations )
161+
162+
foundTokens.identifiers.append(Part.Identifier(number: Int(line[idRange])!, border: borderLocations))
163+
}
164+
}
165+
166+
let parts: [Part] = symbols.reduce(into: [])
167+
{
168+
parts, symbol in
169+
parts.append( Part(
170+
symbol: symbol,
171+
identifiers: identifiers.filter {
172+
$0.border.contains(symbol.location)
173+
})
174+
)
175+
}
176+
177+
let partNumberSum: Int = parts.flatMap(\.numbers).reduce(0, +)
178+
179+
print(partNumberSum)
94180
}
95181
}
96182

0 commit comments

Comments
 (0)