4
\$\begingroup\$

Given an array of integers, update the index with multiplication of previous and next integers,

 Input: 2 , 3, 4, 5, 6
 Output: 2*3, 2*4, 3*5, 4*6, 5*6

Following is a scala implementation for the same. Kindly review.

import scala.util.Random

object NeighborMultiplication extends App {
  val numbers = List.fill(10)(Random.nextInt(10))

  println(numbers mkString ",")

  def multiplication(l: List[Int], carryOver: Int = 1, useCarryOver: Boolean = false ): List[Int] = l match {
    case Nil => List()
    case x::Nil => List(carryOver * x)
    case x::y::Nil => List(carryOver * x * y, y * x)
    case x::y::z::Nil => List(carryOver * x * y, x * z, y * z)
    case x::y::z::tail =>
      if (useCarryOver) List(carryOver * y, x * z, y * tail.head) ++ multiplication(tail, z, true)
      else List(x * y, x * z, y * tail.head) ++ multiplication(tail, z, true)
  }


  println(multiplication(numbers).mkString(","))


}
\$\endgroup\$
5
\$\begingroup\$

The tricky part of this problem is how to handle the special cases for the start and end of the list, as well as how to handle short lists with fewer than three elements.

The fact that you need to consider up to three elements at a time means that you need a lot of base cases for recursion, though. It's also undesirable to expose the special cases in the form of the carryOver and useCarryOver parameters.

A better approach would be to take advantage of the List.sliding function. (Note that .sliding may produce a group with just two elements instead of three, if the input lst has length two.)

def multiplication(lst: List[Int]): List[Int] = lst match {
  case _::_::_ =>
    (lst.head :: lst ++ List(lst.last))
      .sliding(3)
      .map(group => group.head * group.last)
      .toList
  case _ => lst
}
\$\endgroup\$
  • \$\begingroup\$ thanks for your answer, sliding fits here beautifully. \$\endgroup\$ – vikrant Dec 28 '18 at 20:20
1
\$\begingroup\$

This can be done using tail recursion as well.

def mulSeq(numbers: Seq[Int]): Seq[Long] = {
    @tailrec
    def recurMul(numbersPart: Seq[Int], mul: Int, acc: List[Long]): Seq[Long] = {
        numbersPart match {
            case num1::num2::Nil =>
                (num1*num2) :: ((mul*num2).toLong :: acc)
            case num1::num2::tail =>
                recurMul(num2::tail, num1, (mul*num2)::acc)
            case _ =>
                acc
        }
    }

    numbers.headOption match {
    case Some(first) =>
        recurMul(numbers, first, Nil).reverse
    case None =>
        Nil
    }
}

Although the solution above with List.sliding is a little bit shorter, tail recursion is a beloved thing in Scala ^_^. Also, I think in the proposed solution edge cases are more clear.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.