Check if an array is a palindrome in pure immutable Scala

Algorithm goal

A palindrome is a sequence of things that is the same when reversed.

For example, 'aabb' is not a palindrome, 'ababb' is not a palindrome, but 'aba', 'abba' are.

This problem is similar to CheckStringIsAPalindrome and CheckNumberIsAPalindrome

Explanation

The more standard solution is to check Array indices directly, but there is a Scala-idiomatic solution which lets you do it without checking array sizes and indices and so forth.

You could directly compare the array against its reverse, but this means passing through the array three times: once to reverse, and then twice to zip up the array with its reverse, and then compare. (this is © from www.scala-algorithms.com)

In Scala, 'indexed views' provide you with the ability to map an Array to its reverse, and then 'zip' the two arrays together so that you can then compare the last item of the array against the first, one before last with one after after first and so on, thereby doing the check of whether the array is indeed a palindrom

Scala Concepts & Hints

Pattern Matching

Pattern matching in Scala lets you quickly identify what you are looking for in a data, and also extract it.

assert("Hello World".collect {
  case character if Character.isUpperCase(character) => character.toLower
} == "hw")

Read more

Zip

'zip' allows you to combine two lists pair-wise (meaning turn a pair of lists, into a list of pairs)

It can be used over Arrays, Lists, Views, Iterators and other collections.

assert(List(1, 2, 3).zip(List(5, 6, 7)) == List(1 -> 5, 2 -> 6, 3 -> 7))

assert(List(1, 2).zip(List(5, 6, 7)) == List(1 -> 5, 2 -> 6))

assert(List(5, 6).zipWithIndex == List(5 -> 0, 6 -> 1))

Read more

View

The .view syntax creates a structure that mirrors another structure, until "forced" by an eager operation like .toList, .foreach, .forall, .count.

Read more

Algorithm in Scala

7 lines of Scala (version 2.13), showing how concise Scala can be!

def isArrayPalindrome[T](array: Array[T]): Boolean =
  array.view
    .zip(array.reverse.view)
    .forall({
      case (a, b) =>
        a == b
    })

Test cases in Scala

assert(
  isArrayPalindrome(Array(1, 2, 1)),
  "Array of integers is a palindrome"
)
assert(
  isArrayPalindrome(Array('a', 'b', 'a')),
  "Array of Char is a palindrome"
)
assert(isArrayPalindrome(Array(1, 2, 2, 1)), "Even Array is a palindrome")
assert(!isArrayPalindrome(Array(1, 2, 1, 2)), "Array is not a palindrome")
def isArrayPalindrome[T](array: Array[T]): Boolean = ???