Skip to content

Commit 5be792a

Browse files
authored
Add additional tests to rotate functions, clarify variable names (#75)
* Avoid ambiguous single-letter variable names * Use consistent variable names * Add unit tests for documented examples of rotate functions * Add unit tests for reverse functions
2 parents 7ca12be + bf1de32 commit 5be792a

File tree

2 files changed

+78
-18
lines changed

2 files changed

+78
-18
lines changed

Sources/Algorithms/Rotate.swift

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ extension MutableCollection where Self: BidirectionalCollection {
2525
/// Output:
2626
/// [p o n m e f g h i j k l d c b a]
2727
/// ^ ^
28-
/// f l
28+
/// lower upper
2929
///
30-
/// - Postcondition: For returned indices `(f, l)`:
31-
/// `f == limit || l == limit`
30+
/// - Postcondition: For returned indices `(lower, upper)`:
31+
/// `lower == limit || upper == limit`
3232
@usableFromInline
3333
@discardableResult
3434
internal mutating func _reverse(
3535
subrange: Range<Index>, until limit: Index
3636
) -> (Index, Index) {
37-
var f = subrange.lowerBound
38-
var l = subrange.upperBound
39-
while f != limit && l != limit {
40-
formIndex(before: &l)
41-
swapAt(f, l)
42-
formIndex(after: &f)
37+
var lower = subrange.lowerBound
38+
var upper = subrange.upperBound
39+
while lower != limit && upper != limit {
40+
formIndex(before: &upper)
41+
swapAt(lower, upper)
42+
formIndex(after: &lower)
4343
}
44-
return (f, l)
44+
return (lower, upper)
4545
}
4646

4747
/// Reverses the elements within the given subrange.
@@ -59,13 +59,12 @@ extension MutableCollection where Self: BidirectionalCollection {
5959
@inlinable
6060
public mutating func reverse(subrange: Range<Index>) {
6161
if subrange.isEmpty { return }
62-
var lo = subrange.lowerBound
63-
var hi = subrange.upperBound
64-
65-
while lo < hi {
66-
formIndex(before: &hi)
67-
swapAt(lo, hi)
68-
formIndex(after: &lo)
62+
var lower = subrange.lowerBound
63+
var upper = subrange.upperBound
64+
while lower < upper {
65+
formIndex(before: &upper)
66+
swapAt(lower, upper)
67+
formIndex(after: &lower)
6968
}
7069
}
7170
}

Tests/SwiftAlgorithmsTests/RotateTests.swift

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,70 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
import XCTest
13-
import Algorithms
13+
@testable import Algorithms
1414

1515
final class RotateTests: XCTestCase {
16+
/// Tests the example given in `_reverse(subrange:until:)`’s documentation
17+
func testUnderscoreReverse() {
18+
var input = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"]
19+
let limit: Int = 4
20+
let (lower, upper) = input._reverse(subrange: input.startIndex..<input.endIndex, until: input.startIndex.advanced(by: limit))
21+
let expected = ["p", "o", "n", "m", "e", "f", "g", "h", "i", "j", "k", "l", "d", "c", "b", "a"]
22+
XCTAssertEqual(input, expected)
23+
XCTAssertEqual(lower, input.startIndex.advanced(by: limit))
24+
XCTAssertEqual(upper, input.endIndex.advanced(by: -limit))
25+
}
26+
27+
/// Tests the example given in `reverse(subrange:)`’s documentation
28+
func testReverse() {
29+
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
30+
numbers.reverse(subrange: 0..<4)
31+
XCTAssertEqual(numbers, [40, 30, 20, 10, 50, 60, 70, 80])
32+
}
33+
34+
/// Tests `rotate(subrange:toStartAt:)` with an empty subrange
35+
/// The order of elements are unchanged
36+
func testRotateEmptySubrange() {
37+
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
38+
let oldStart = numbers.rotate(subrange: 3..<3, toStartAt: 3)
39+
XCTAssertEqual(numbers, [10, 20, 30, 40, 50, 60, 70, 80])
40+
XCTAssertEqual(numbers[oldStart], 40)
41+
}
42+
43+
/// Tests `rotate(subrange:toStartAt:)` with an empty collection
44+
func testRotateSubrangeOnEmptyCollection() {
45+
var numbers = [Int]()
46+
let oldStart = numbers.rotate(subrange: 0..<0, toStartAt: 0)
47+
XCTAssertEqual(numbers, [])
48+
XCTAssertEqual(oldStart, numbers.startIndex)
49+
}
50+
51+
/// Tests `rotate(subrange:toStartAt:)` with the full range of the collection
52+
func testRotateFullRange() {
53+
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
54+
let oldStart = numbers.rotate(subrange: 0..<8, toStartAt: 1)
55+
XCTAssertEqual(numbers, [20, 30, 40, 50, 60, 70, 80, 10])
56+
XCTAssertEqual(numbers[oldStart], 10)
57+
}
58+
59+
/// Tests the example given in `rotate(subrange:toStartAt:)`’s documentation
60+
func testRotateSubrange() {
61+
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
62+
let oldStart = numbers.rotate(subrange: 0..<4, toStartAt: 2)
63+
XCTAssertEqual(numbers, [30, 40, 10, 20, 50, 60, 70, 80])
64+
XCTAssertEqual(numbers[oldStart], 10)
65+
}
66+
67+
/// Tests the example given in `rotate(toStartAt:)`’s documentation
68+
func testRotateExample() {
69+
var numbers = [10, 20, 30, 40, 50, 60, 70, 80]
70+
let oldStart = numbers.rotate(toStartAt: 3)
71+
XCTAssertEqual(numbers, [40, 50, 60, 70, 80, 10, 20, 30])
72+
XCTAssertEqual(numbers[oldStart], 10)
73+
}
74+
75+
/// Tests `rotate(toStartAt:)` on collections of varying lengths, at different
76+
/// starting points
1677
func testRotate() {
1778
for length in 0...15 {
1879
let a = Array(0..<length)

0 commit comments

Comments
 (0)