Skip to content

Commit 9dd88e5

Browse files
authored
CombinationsSequence: underestimatedCount == count (#220)
Not doing this makes it needlessly costly to create an Array of the results.
1 parent c3b3acb commit 9dd88e5

File tree

2 files changed

+55
-45
lines changed

2 files changed

+55
-45
lines changed

Sources/Algorithms/Combinations.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ public struct CombinationsSequence<Base: Collection> {
7878
binomial(n: n, k: $0)
7979
}.reduce(0, +)
8080
}
81+
82+
/// The total number of combinations.
83+
@inlinable
84+
public var underestimatedCount: Int { count }
8185
}
8286

8387
extension CombinationsSequence: Sequence {

Tests/SwiftAlgorithmsTests/CombinationsTests.swift

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,57 +15,63 @@ import Algorithms
1515
final class CombinationsTests: XCTestCase {
1616
func testCount() {
1717
let c = "ABCD"
18-
19-
let c0 = c.combinations(ofCount: 0).count
20-
XCTAssertEqual(c0, 1)
21-
22-
let c1 = c.combinations(ofCount: 1).count
23-
XCTAssertEqual(c1, 4)
24-
25-
let c2 = c.combinations(ofCount: 2).count
26-
XCTAssertEqual(c2, 6)
27-
28-
let c3 = c.combinations(ofCount: 3).count
29-
XCTAssertEqual(c3, 4)
30-
31-
let c4 = c.combinations(ofCount: 4).count
32-
XCTAssertEqual(c4, 1)
33-
34-
let c5 = c.combinations(ofCount: 0...0).count
35-
XCTAssertEqual(c5, 1)
36-
37-
let c6 = c.combinations(ofCount: 1...1).count
38-
XCTAssertEqual(c6, 4)
39-
40-
let c7 = c.combinations(ofCount: 1...2).count
41-
XCTAssertEqual(c7, 10)
42-
43-
let c8 = c.combinations(ofCount: 1...3).count
44-
XCTAssertEqual(c8, 14)
45-
46-
let c9 = c.combinations(ofCount: 2...4).count
47-
XCTAssertEqual(c9, 11)
48-
18+
19+
/// XCTAsserts that `x`'s `count` and `underestimatedCount` are both `l` at
20+
/// the given `file` and `line`.
21+
func check(
22+
_ x: CombinationsSequence<String>, countsAre l: Int,
23+
file: StaticString, line: UInt)
24+
{
25+
XCTAssertEqual(x.count, l, "unexpected count", file: file, line: line)
26+
XCTAssertEqual(
27+
x.underestimatedCount, l, "unexpected underestimatedCount",
28+
file: file, line: line)
29+
}
30+
31+
/// XCTAsserts that the `count` and `underestimatedCount` of
32+
/// `c.combinations(ofCount: l)` are both `n` at the given `file` and
33+
/// `line`.
34+
func check(
35+
cHas n: Int,
36+
combinationsOfLength l: Int,
37+
file: StaticString = #filePath, line: UInt = #line)
38+
{
39+
check(c.combinations(ofCount: l), countsAre: n, file: file, line: line)
40+
}
41+
42+
/// XCTAsserts that the `count` and `underestimatedCount` of
43+
/// `c.combinations(ofCount: l)` are both `n` at the given `file` and
44+
/// `line`.
45+
func check<R: RangeExpression>(
46+
cHas n: Int,
47+
combinationsOfLengths l: R,
48+
file: StaticString = #filePath, line: UInt = #line) where R.Bound == Int
49+
{
50+
check(c.combinations(ofCount: l), countsAre: n, file: file, line: line)
51+
}
52+
53+
check(cHas: 1, combinationsOfLength: 0)
54+
check(cHas: 4, combinationsOfLength: 1)
55+
check(cHas: 6, combinationsOfLength: 2)
56+
check(cHas: 1, combinationsOfLength: 4)
57+
58+
check(cHas: 1, combinationsOfLengths: 0...0)
59+
check(cHas: 4, combinationsOfLengths: 1...1)
60+
check(cHas: 10, combinationsOfLengths: 1...2)
61+
check(cHas: 14, combinationsOfLengths: 1...3)
62+
check(cHas: 11, combinationsOfLengths: 2...4)
63+
4964
// `k` greater than element count results in same number of combinations
50-
let c10 = c.combinations(ofCount: 3...10).count
51-
XCTAssertEqual(c10, 5)
65+
check(cHas: 5, combinationsOfLengths: 3...10)
5266

5367
// `k` greater than element count results in same number of combinations
54-
let c11 = c.combinations(ofCount: 4...10).count
55-
XCTAssertEqual(c11, 1)
68+
check(cHas: 1, combinationsOfLengths: 4...10)
5669

5770
// `k` entirely greater than element count results in no combinations
58-
let c12 = c.combinations(ofCount: 5...10).count
59-
XCTAssertEqual(c12, 0)
60-
61-
let c13 = c.combinations(ofCount: 0...).count
62-
XCTAssertEqual(c13, 16)
63-
64-
let c14 = c.combinations(ofCount: ...3).count
65-
XCTAssertEqual(c14, 15)
71+
check(cHas: 0, combinationsOfLengths: 5...10)
6672

67-
let c15 = c.combinations(ofCount: 0...).count
68-
XCTAssertEqual(c15, 16)
73+
check(cHas: 16, combinationsOfLengths: 0...)
74+
check(cHas: 15, combinationsOfLengths: ...3)
6975
}
7076

7177
func testCombinations() {

0 commit comments

Comments
 (0)