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(","))
}
2 Answers 2
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
}
-
\$\begingroup\$ thanks for your answer, sliding fits here beautifully. \$\endgroup\$vikrant– vikrant2018年12月28日 20:20:04 +00:00Commented Dec 28, 2018 at 20:20
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.
Explore related questions
See similar questions with these tags.