Scala algorithm: Rotate Array right in pure-functional Scala - using an unusual immutable efficient approach
Published
Algorithm goal
Rotating the array \([1,2,3]\) by 1 element to the right returns an array \([3,1,2]\). Example:
1 | 2 | 3 |
3 | 1 | 2 |
2 | 3 | 1 |
Rotating the array \([1,2,3]\) 3 times returns us to the original array \([1,2,3]\).
Test cases in Scala
assert(countToDrop(length = 0, rightShift = 0) == 0)
assert(countToDrop(length = 1, rightShift = 0) == 1)
assert(countToDrop(length = 5, rightShift = 0) == 5)
assert(countToDrop(length = 5, rightShift = 1) == 4)
assert(countToDrop(length = 5, rightShift = 5) == 5)
assert(countToDrop(length = 4, rightShift = 2) == 2)
assert(rotateArrayRight(Array(), 3).isEmpty)
assert(rotateArrayRight(Array(1), 3).toVector == Vector(1))
assert(rotateArrayRight(Array(1, 2), 0).toVector == Vector(1, 2))
assert(
rotateArrayRight(Array(1, 2, 3, 4), 1).toVector == Vector(4, 1, 2, 3)
)
assert(
rotateArrayRight(Array(1, 2, 3, 4), 5).toVector == Vector(4, 1, 2, 3)
)
Algorithm in Scala
8 lines of Scala (compatible versions 2.13 & 3.0), showing how concise Scala can be!
Explanation
The most tricky part is finding the trick - which is to join two Arrays side-by-side, and then slice that array to get a continuous slice that simulates a rotation - no mutations needed!
In Scala, we use the View concept to turn our array \([1,2,3]\) into an array \([1,2,3,1,2,3]\) with concatenation (without doing any allocations yet!), and then select the expected slice. (this is © from www.scala-algorithms.com)
For example, when \(n = 1\):
1 | 2 | 3 | 1 | 2 | 3 |
Scala concepts & Hints
Drop, Take, dropRight, takeRight
Scala's `drop` and `take` methods typically remove or select `n` items from a collection.
View
The
.view
syntax creates a structure that mirrors another structure, until "forced" by an eager operation like .toList, .foreach, .forall, .count.