Skip to content

Commit 345ea04

Browse files
committed
Avoid counting base more than once
This is similar to how `Permutations` works
1 parent fbf3ad6 commit 345ea04

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

Sources/Algorithms/Combinations.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ public struct Combinations<Base: Collection> {
1414
/// The collection to iterate over for combinations.
1515
public let base: Base
1616

17+
@usableFromInline
18+
internal let baseCount: Int
19+
1720
/// The range of accepted sizes of combinations.
1821
/// - Note: This may be `nil` if the attempted range entirely exceeds the
1922
/// upper bounds of the size of the `base` collection.
@@ -40,18 +43,20 @@ public struct Combinations<Base: Collection> {
4043
) where R.Bound == Int {
4144
let range = kRange.relative(to: 0 ..< .max)
4245
self.base = base
43-
let upperBound = base.count + 1
46+
let baseCount = base.count
47+
self.baseCount = baseCount
48+
let upperBound = baseCount + 1
4449
self.kRange = range.lowerBound < upperBound
45-
? range.clamped(to: 0..<upperBound)
50+
? range.clamped(to: 0 ..< upperBound)
4651
: nil
4752
}
4853

4954
/// The total number of combinations.
5055
@inlinable
5156
public var count: Int {
5257
guard let k = self.kRange else { return 0 }
53-
let n = base.count
54-
if k == 0..<(n + 1) {
58+
let n = baseCount
59+
if k == 0 ..< (n + 1) {
5560
return 1 << n
5661
}
5762

@@ -123,7 +128,7 @@ extension Combinations: Sequence {
123128
func advanceKRange() {
124129
if kRange.lowerBound < kRange.upperBound {
125130
let advancedLowerBound = kRange.lowerBound + 1
126-
kRange = advancedLowerBound..<kRange.upperBound
131+
kRange = advancedLowerBound ..< kRange.upperBound
127132
indexes.removeAll(keepingCapacity: true)
128133
indexes.append(contentsOf: base.indices.prefix(kRange.lowerBound))
129134
}

0 commit comments

Comments
 (0)