1. Introduction

In programming, rotating an array often comes in handy when accomplishing certain tasks. Rotating an array means shifting the elements of an array by a certain number of positions ahead or behind.

In this tutorial, we’ll discuss various ways to cyclically rotate an array by one in Kotlin. This simply means shifting the elements by one position to the right.

2. Programmatic Approach

A straightforward way to cyclically rotate an array by one involves using a temporary variable and a classic for() loop. Basically, we store the last element of the array in a temporary variable and shift all other elements of the array to the right by one position. Finally, we place the temporary variable at the beginning of the array:

fun rotateArrayByOneProgramaticApproach(arr: IntArray) {
    val temp = arr.last()
    for (i in arr.size - 1 downTo 1) {
        arr[i] = arr[i - 1]
    }
    arr[0] = temp
}

Now, let’s test our method to be certain it works as expected:

@Test
fun `cyclically rotate an array by one position using programmatic approach`() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    rotateArrayByOneProgramaticApproach(arr)
    assertArrayEquals(intArrayOf(5, 1, 2, 3, 4), arr)
}

3. Using the copyInto() Method

We can equally use Kotlin’s built-in copyInto() method to cyclically rotate an array by one. This method copies the elements of an array into a new array.

This method accepts four parameters in the following order:

  • The array to copy elements into
  • The offset index position to begin copying the elements into
  • The starting index of the original array to start picking elements from
  • The end index (exclusive) from the original array that indicates where to stop picking elements from
fun rotateArrayByOneUsingCopyIntoMethod(arr: IntArray) {
    val newArr = IntArray(arr.size)
    arr.copyInto(newArr, 1, 0, arr.size - 1)
    newArr.set(0, arr[arr.size - 1])
    newArr.copyInto(arr)
    }

In this code, we move all the elements except the last one from the original array into a new array using the copyInto() method. Notice that we are skipping the first position of the new array initially as we copy elements in.

Finally, we use the set() method to place the last element of the original array in the first position of the new array.

Let’s also test this method:

@Test
fun `cyclically rotate an array by one position using copyInto method`() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    rotateArrayByOneUsingCopyIntoMethod(arr)
    assertArrayEquals(intArrayOf(5, 1, 2, 3, 4), arr)
}

4. Using the takeLast() and dropLast() Methods

Alternatively, we can achieve our goal by using the takeLast() and dropLast() methods. However, these methods return List objects:

fun rotateArrayByOneUsingDropLastAndTakeLastMethods(arr: IntArray): Array<Int> {
    val newArray = (arr.takeLast(1) + arr.dropLast(1)).toIntArray()
    newArray.copyInto(arr)
}

Within this code, we call the takeLast() method with a parameter of one, which allows us to acquire a list that contains the last element of the array. Next, we call the dropLast() method also with a parameter of one to obtain a list containing all of the array elements except for the last one.

We then concatenate the results from both methods using the plus operator, convert the combined list back into an array, and finally, return this shifted array.

Let’s also verify this method for correctness:

 @Test
fun `cyclically rotate an array by one position using dropLast and takeLast methods`() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    rotateArrayByOneUsingDropLastAndTakeLastMethods(arr)
    assertArrayEquals(intArrayOf(5, 1, 2, 3, 4), arr)
}

5. Using the Collections.rotate() Method

We can also leverage the Collections.rotate() method to cyclically rotate an array by one. However, this method requires that we convert our array into a list first, perform the rotation, and then convert the list back to an array:

fun rotateArrayByOneUsingCollectionsRotateMethod(arr: IntArray) {
    val list = arr.toList().toMutableList()
    Collections.rotate(list, 1)
    list.toIntArray().copyInto(arr)
}

The aforementioned code involves passing the list we intend to rotate and the distance we want to rotate it to the Collections.rotate() method. Lastly, we convert the rotated list into an array and copy the array elements into our original array using the copyInto() method.

We should also test this method:

@Test
fun `cyclically rotate an array by one position using Collections rotate methods`() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    rotateArrayByOneUsingCollectionsRotateMethod(arr)
    assertArrayEquals(intArrayOf(5, 1, 2, 3, 4), arr)
}

6. Using Recursion

Lastly, we can cyclically rotate an array by using recursion:

fun rotateArrayByOneUsingRecursion(arr: IntArray, position: Int = 0) {
    if (position == arr.size - 1) return
    val temp = arr[position]
    arr[position] = arr[arr.size - 1]
    arr[arr.size - 1] = temp
    rotateArrayByOneUsingRecursion(arr, position + 1)
}

In this method, we pass in the original array and an index position. The position has a default value of zero to start at the beginning of the array. Next, we recursively swap the array elements in the given index position and the last index position of the array and increment the given index position in each step until we reach the end of the array.

Now, let’s test this method to be sure it works as expected:

@Test
fun `cyclically rotate an array by one position using recursion`() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    rotateArrayByOneUsingRecursion(arr)
    assertArrayEquals(intArrayOf(5, 1, 2, 3, 4), arr)
}

7. Conclusion

In this article, we’ve explored how to cyclically rotate an array by one in Kotlin using various approaches.

Some of the approaches we’ve discussed solely use Kotlin arrays, such as the programmatic and recursive approaches, while the other approaches make use of Kotlin built-in methods such as copyInto(), takeLast(), dropLast(), and Collections.rotate() methods. However, all of these methods except for copyInto() end up with a list, which means we must convert the list back to an array.

Our choice of which approach to adopt should depend on our project needs.

As always, the code used in this article is available over on GitHub.