Skip to content

Commit a25130b

Browse files
committed
Inline remaining calculation
1 parent d9873a8 commit a25130b

File tree

1 file changed

+24
-38
lines changed

1 file changed

+24
-38
lines changed

19.swift

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,13 @@ func isAccepted(workflows: Workflows, part: Part) -> Bool {
141141
}
142142

143143
func filterRanges(workflows: Workflows) -> Int {
144-
let attributeRanges: AttributeRanges =
145-
Dictionary(uniqueKeysWithValues: [.x, .m, .a, .s].map { ($0, 1...4000) })
144+
func combinations(_ attributeRanges: [Attribute: ClosedRange<Int>]) -> Int {
145+
attributeRanges.values.reduce(1, { $0 * $1.count })
146+
}
147+
148+
let attributes: [Attribute] = [.x, .m, .a, .s]
149+
let attributeRanges =
150+
Dictionary(uniqueKeysWithValues: attributes.map { ($0, 1...4000) })
146151
var pending = [("in", attributeRanges)]
147152
var acceptedCount = 0
148153

@@ -154,8 +159,9 @@ func filterRanges(workflows: Workflows) -> Int {
154159

155160
// Find the range to which this rule applies.
156161
let attribute = condition.attribute
162+
let validRange = condition.validRange
157163
let range = attributeRanges[attribute]!
158-
let newRange = range.clamped(to: condition.validRange)
164+
let newRange = range.clamped(to: validRange)
159165

160166
// Create a new set of attribute ranges with this range, and
161167
// apply the rule's action to it.
@@ -165,34 +171,34 @@ func filterRanges(workflows: Workflows) -> Int {
165171
case .reject:
166172
break
167173
case .accept:
168-
acceptedCount += combinations(attributeRanges: newAttributeRanges)
174+
acceptedCount += combinations(newAttributeRanges)
169175
case .send(let newWorkflow):
170176
pending.append((newWorkflow, newAttributeRanges))
171177
}
172178

173179
// There will be a leftover range, possibly empty. Continue
174180
// processing it if it is not empty.
175-
let remaining = remainingNonEmptyRanges(
176-
range: attributeRanges[condition.attribute]!,
177-
validRange: condition.validRange)
178-
// If there are zero of them, then we're done with this pending
179-
// entry
180-
if remaining.count == 0 { continue nextPending }
181-
// If there is one of them, that continues on with the sequence
182-
// of rules in this workflow.
183-
if remaining.count == 1 {
184-
attributeRanges[condition.attribute] = remaining[0]
181+
//
182+
// Because of how the problem is structured, either the leftover
183+
// range will be of values lower than the valid range, or of
184+
// values above the valid range, but it won't span both.
185+
if range.lowerBound < validRange.lowerBound {
186+
attributeRanges[attribute] =
187+
range.lowerBound...(validRange.lowerBound - 1)
188+
} else if validRange.upperBound < range.upperBound {
189+
attributeRanges[attribute] =
190+
(validRange.upperBound + 1)...range.upperBound
185191
} else {
186-
// 2 of them. Haven't handled this case yet
187-
fatalError("found 2 remaining entries \(remaining)")
192+
continue nextPending
188193
}
189194
} else {
190-
// Unconditional rule, always a match, so consumes the whole ranges
195+
// Unconditional rule, always a match, so consumes the whole.
196+
// ranges
191197
switch rule.action {
192198
case .reject:
193199
break
194200
case .accept:
195-
acceptedCount += combinations(attributeRanges: attributeRanges)
201+
acceptedCount += combinations(attributeRanges)
196202
case .send(let newWorkflow):
197203
pending.append((newWorkflow, attributeRanges))
198204
}
@@ -204,26 +210,6 @@ func filterRanges(workflows: Workflows) -> Int {
204210
return acceptedCount
205211
}
206212

207-
typealias AttributeRanges = [Attribute: ClosedRange<Int>]
208-
209-
func combinations(attributeRanges: AttributeRanges) -> Int {
210-
attributeRanges.values.reduce(1, { $0 * $1.count })
211-
}
212-
213-
func remainingNonEmptyRanges(range: ClosedRange<Int>, validRange: ClosedRange<Int>
214-
) -> [ClosedRange<Int>] {
215-
var result = [ClosedRange<Int>]()
216-
// Before valid range
217-
if range.lowerBound < validRange.lowerBound {
218-
result.append(range.lowerBound...(validRange.lowerBound - 1))
219-
}
220-
// After valid range
221-
if validRange.upperBound < range.upperBound {
222-
result.append((validRange.upperBound + 1)...range.upperBound)
223-
}
224-
return result
225-
}
226-
227213
let (workflows, parts) = readInput()
228214
let p1 = process(workflows: workflows, parts: parts)
229215
let p2 = filterRanges(workflows: workflows)

0 commit comments

Comments
 (0)