Sums of different lists using recursion - scala

I am doing CodeWars challenges again and today I have a problem with this one:
Let us consider this example (array written in general format):
ls = [0, 1, 3, 6, 10]
Its following parts:
ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []
The corresponding sums are (put together in a list): [20, 20, 19, 16, 10, 0]
The function parts_sums (or its variants in other languages) will take as parameter a list ls and return a list of the sums of its parts as defined above.
object SumsOfParts {
def partsSums(l: List[Int]): List[Int] = {
var x: List[Int] = List()
if (l.isEmpty)
x
else {
x :+ l.sum
partsSums(l.tail)
}
}
}
Here are the test samples:
partsSums(List(0, 1, 3, 6, 10)) should return List(20, 20, 19, 16, 10, 0)
Test Failed
tail of empty list
Stack Trace
Completed in 4ms
partsSums(List(1, 2, 3, 4, 5, 6)) should return List(21, 20, 18, 15, 11, 6, 0)
Test Failed
tail of empty list
Stack Trace
partsSums(List(744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358)) should return List(10037855, 9293730, 9292795, 9292388, 9291934, 9291504, 9291414, 9291270, 2581057, 2580168, 2579358, 0)
Test Failed
tail of empty list
Stack Trace
Completed in 1ms
partsSums(List(30350, 76431, 156228, 78043, 98977, 80169, 32457, 182875, 162323, 17508, 57971, 171907)) should return List(1145239, 1114889, 1038458, 882230, 804187, 705210, 625041, 592584, 409709, 247386, 229878, 171907, 0)
Test Failed

You shouldn't use var in your recursive functions to pass state. You could fix your method like that:
def partsSums(l: List[Int]): List[Int] = {
if (l.isEmpty)
Nil //to finish recursion return empty list
else {
l.sum :: partsSums(l.tail) //prepend newly calculated sum to list returned by recursive call
}
}
But this solution is naive since it recalculates sum on every iteration. We could make it better taking the previous sum from the head of the result and calculating the new sum by just adding it to the head of the list. I also use another list called acc to accumulate results, because this way I can make partsSums2 tail-recursive:
def partsSums2(l: List[Int], acc: List[Int] = List(0)): List[Int] = {
if(l.isEmpty) {
acc //at the end of recursion we return acc, which holds result
} else {
//acc.head is previos sum and l.head is value I want to add
partsSums2(l.tail, (l.head + acc.head) :: acc)
}
}
In order to make it work we also need to reverse list before passing to method:
SumsOfParts.partsSums2(List(0, 1, 3, 6, 10).reverse)
We need to reverse the list because the implementation of the immutable list in Scala is very affective on prepend operations (O(1)), but not on append operations (O(n)).
Finally you could just use scanRight:
def partsSums3(l: List[Int]): List[Int] = l.scanRight(0)(_ + _)

As #Andrey commented scanLeft solves this problem, but here is a recursive solution:
def partsSums(l: List[Int]): List[Int] = {
if (l.isEmpty) {
Nil
} else {
def go(list: List[Int], acc: List[Int], currentSum: Int): List[Int] =
list match {
case Nil => (0 :: acc).reverse
case x :: xs =>
go(xs, currentSum :: acc, currentSum - x)
}
go(l, Nil, l.sum)
}
}
def main(args: Array[String]): Unit = {
println(partsSums(List(0, 1, 3, 6, 10)))
// List(20, 20, 19, 16, 10, 0)
println(partsSums(List(1, 2, 3, 4, 5, 6)))
// List(21, 20, 18, 15, 11, 6, 0)
println(partsSums(List(744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358)))
// List(10037855, 9293730, 9292795, 9292388, 9291934, 9291504, 9291414, 9291270, 2581057, 2580168, 2579358, 0)
println(partsSums(List(30350, 76431, 156228, 78043, 98977, 80169, 32457, 182875, 162323, 17508, 57971, 171907)))
// List(1145239, 1114889, 1038458, 882230, 804187, 705210, 625041, 592584, 409709, 247386, 229878, 171907, 0)
}

Related

Convert Loop problem to Recursive Solution in Scala

I've written the following method (working perfectly fine) which takes a list and returns a list of lists containing the
elements, so that the first list contains half of list’s elements, the next contains half of the remaining elements, and so on. For example,
repHalve(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15))
Returning:
List(List(1, 2, 3, 4, 5, 6, 7, 8), List(9, 10, 11, 12), List(13, 14), List(15))
The question is I'm new to Scala and wanted to convert this method to recursive approach. Please let me know how should I convert this. I know the base case could be the same as the condition inside while loop but still unable to figure it out. Any help would be highly appreciated. Thanks
def repHalve(list:List[Any]){
var local_list:List[Any] = list
var list_of_lists:List[Any] = List.empty
while(local_list.length>1){
val sub = local_list.slice(0, (local_list.length/2)+1)
list_of_lists ++= List(sub)
local_list = local_list.slice(local_list.length/2+1, local_list.length)
}
list_of_lists ++= List(List(list.last))
println(list_of_lists)
}
Consider analogous solution to Luis' but using splitAt
def repHalve(l: List[Int]): List[List[Int]] = {
def half(i: Int): Int = if ((i % 2) == 0) i / 2 else (i + 1) / 2
#annotation.tailrec
def loop(l: List[Int], size: Int, acc: List[List[Int]]): List[List[Int]] = l match {
case x :: Nil => (List(x) :: acc).reverse
case _ =>
val (left, right) = l.splitAt(half(size))
loop(right, right.size, left :: acc)
}
loop(l, l.size, Nil)
}
jmh benchmark using (1 to 200).toList as input indicates Luis' solution is faster
[info] So60178352._luis thrpt 5 666357.490 ± 165323.129 ops/s
[info] So60178352._mario thrpt 5 591174.959 ± 118097.426 ops/s
Here is a completely tail-recursive implementation.
Let me know if you have any questions.
def repHalve[T](list: List[T]): List[List[T]] = {
def half(i: Int): Int =
if ((i % 2) == 0) i / 2 else (i + 1) / 2
#annotation.tailrec
def loop(remaining: List[T], targetLength: Int, acc: List[List[T]]): List[List[T]] =
remaining match {
case Nil => acc.reverse
case list =>
#annotation.tailrec
def innerLoop(remaining: List[T], currentLength: Int, acc: List[T]): (List[T], List[T]) =
remaining match {
case x :: xs =>
if (currentLength != targetLength)
innerLoop(remaining = xs, currentLength + 1, x :: acc)
else
(x :: xs, acc.reverse)
case Nil =>
(Nil, acc.reverse)
}
val (remaining, newList) = innerLoop(remaining = list, currentLength = 0, acc = List.empty)
loop(remaining, half(targetLength), newList :: acc)
}
loop(remaining = list, targetLength = half(list.length), acc = List.empty)
}
Which you can use like this:
repHalve((1 to 20).toList)
// res: List[List[Int]] = List(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), List(11, 12, 13, 14, 15), List(16, 17, 18), List(19, 20))

List of Lists: how to add a trailing 0 for each List except the last one?

List of Lists: how to add a trailing 0 for each List except the last one?
I'm learning Scala. I have a List of Lists, like below:
List(List(1,2,3), List(15, 17, 21), List(28, 5, 7))
My aim is to add a trailing 0 for each List except the last one, like below:
List(List(1,2,3, 0), List(15, 17, 21, 0), List(28, 5, 7))
My solution is like below:
def addZero(lines: List[List[Int]]): List[Int] = {
def helper(nums: List[Int]): List[Int] = nums match {
case Nil => 0 :: Nil
case hd :: tl => hd :: helper(tl)
}
lines match {
case Nil => Nil
case hd :: Nil => hd
case hd :: tl => helper(hd) ++ addZero(tl)
}
}
But I'm not sure if there is more elegant way. I tried flatMap and foldLeft but they add 0 to every List
including the last one.
list.init.map { _ :+ 0 } :+ list.last
You could do that:
List(List(1, 2, 3), List(15, 17, 21), List(28, 5, 7)) match {
case begin :+ last => begin.map(_ :+ 0) :+ last
}
In details: you first pattern match the list of lists in order to easily extract the elements of the list which are not the last one.
"begin" represents List(List(1, 2, 3), List(15, 17, 21))
"last" represents List(28, 5, 7)
You then add the 0 in last position of each list
_ :+ 0 // List(15, 17, 21) => List(15, 17, 21, 0)
And finally you add back the last element

How to split a collection into groups using the calculation of member as a predicate

I have a method that collect the consecutive number with the difference of no more than some number (2 in my example). This code is working just fine but it does zipping every time it is called, so I wonder if there is any better solution to this thanks.
def myGrouper(sortedData: Seq[Int], maxDif: Int): Seq[Seq[Int]] = sortedData match {
case Nil => Nil
case _ =>
val (grouped, rest) = sortedData.zipWithIndex.span{
case (num, idx) =>
if (idx > 1) Math.abs(sortedData(idx-1) - num) <= maxDif
else true
}
Seq(grouped.map(_._1)) ++ myGrouper(rest.map(_._1), maxDif)
}
val myList = Seq(1, 2, 3, 7, 8, 10, 15, 17, 19)
val maxDif = 2
println(myGrouper(myList, maxDif))
Below is the result from running this code
myList: Seq[Int] = List(1, 2, 3, 7, 8, 10, 15, 17, 19)
maxDif: Int = 2
List(List(1, 2, 3), List(7, 8, 10), List(15, 17, 19))
res0: Unit = ()

Generate sequence with unknown bound, based on condition

I want to generate sequance of all fibonacci numbers, that less then 10000
For example, this will generate 40 fibonacci numbers. But i want to stop generate them with some condition. How can i do this?
def main(args: Array[String]) {
val fibonacciSequence = for(i <- 1 to 40) yield fibonacci(i)
println(fibonacciSequence)
}
def fibonacci(i: Int) : Int = i match {
case 0 => 0
case 1 => 1
case _ => fibonacci(i - 1) + fibonacci(i - 2);
}
I want something like this: for(i <- 1 to ?; stop if fibonacci(i) > 100000)
This method, involving lazy infinite collection calculation, could produce suitable result:
import scala.Numeric.Implicits._
def fibonacci[N: Numeric](a: N, b: N): Stream[N] = a #:: fibonacci(b, a + b)
so
fibonacci(0L,1L).takeWhile(_ < 1000L).toList
yields
List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987)
If you don't want to use intermediate value to cache collection of proper type and init, you could just declare a val like this:
val fib: Stream[Long] = 0 #:: 1 #:: (fib zip fib.tail map { case (a, b) => a + b })
Using iterators and memoization (computing the current result based in the latest ones, not recomputing what has already been done), (method from Rosetta, similar to Odomontois's streams),
def fib() = Iterator.iterate((0,1)){ case (a,b) => (b,a+b)}.map(_._1)
To get the first nth values consider for instance,
def nfib(n: Int) = fib().zipWithIndex.takeWhile(_._2 < n).map(_._1).toArray
To get consecutive values up to a given condition or predicate,
def pfib(p: Int => Boolean) = fib().takeWhile(p).toArray
Thus, for example
nfib(10)
Array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
pfib( _ < 55)
Array(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)

Get list of primes to N

I'm trying to write a function which takes an Int and returns all of the prime numbers up to and including that Int.
for example "list of primes for 8" = List(3,5,7)
This is what I have so far :
def isPrime(i: Int): Boolean = {
if (i <= 1)
false
else if (i == 2)
true
else
!(2 to (i - 1)).exists(x => i % x == 0)
} //> isPrime: (i: Int)Boolean
def getListOfPrimesToN(n : Int) = {
}
for the function getListOfPrimesToN I plan to
1. create a List "l" of size n and populate it with elements ranging from 0 to n.
2. call map function of "l" and call isPrime for each element in List.
How to create the List of element 1 to N ?
Any alternative solutions for returning all of the prime numbers up to and including an Int N welcome.
You can solve this with infinite streams. If you had a stream primes of all the primes, you could just say primes.takeWhile(_ <= n) to get the primes up to and including n.
To get all the primes, you start with a stream of all the numbers starting from 2, the first prime. You can then skip all the even numbers since those are definitely not prime. Then you can skip all the other numbers that are not prime.
val primes = 2 #:: Stream.from(3,2).filter(isPrime)
Now you just need isPrime to check if a given number is prime. A number is prime if it is not divisible by any smaller prime. We actually need only consider primes whose square is not greater than the number (since, logically, a composite number's smallest prime factor can't be larger than its square root).
def isPrime(n: Int): Boolean =
primes.takeWhile(p => p*p <= n).forall(n % _ != 0)
Check this in the REPL:
scala> primes.takeWhile(_ <= 8).toList
res0: List[Int] = List(2, 3, 5, 7)
Caveat: This only works for positive numbers smaller than Integer.MAX_VALUE.
An implementation of the Sieve of Eratosthenes algorithm for efficiently finding prime numbers up to a given value N includes the following, (fixed and improved on this SO answer),
implicit class Sieve(val N: Int) extends AnyVal {
def primesUpTo() = {
val isPrime = collection.mutable.BitSet(2 to N: _*) -- (4 to N by 2)
for (p <- 2 +: (3 to Math.sqrt(N).toInt by 2) if isPrime(p)) {
isPrime --= p*p to N by p
}
isPrime.toImmutable
}
}
Hence
10.primesUpTo.toList
res: List(2, 3, 5, 7)
11.primesUpTo.toList
res: List(2, 3, 5, 7, 11)
Note Find prime numbers using Scala. Help me to improve for additional ideas and discussion.
Here is the code based on your:
scala> def isPrime(n: Int): Boolean =
| n >= 2 && (2 to math.sqrt(n).toInt).forall(n%_ != 0)
isPrime: (n: Int)Boolean
scala> def getListOfPrimesToN(n: Int): List[Int] =
| List.range(2, n+1) filter isPrime
getListOfPrimesTON: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
Here is another solution using Stream:
scala> def getListOfPrimesToN(n: Int): List[Int] = {
| lazy val ps: Stream[Int] = 2 #:: Stream.from(3)
.filter(x => ps.takeWhile(p => p*p <= x).forall(x%_ != 0))
| ps.takeWhile(_ <= n).toList
| }
getListOfPrimesToN: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
How about this.
def getPrimeUnder(n: Int) = {
require(n >= 2)
val ol = 3 to n by 2 toList // oddList
def pn(ol: List[Int], pl: List[Int]): List[Int] = ol match {
case Nil => pl
case _ if pl.exists(ol.head % _ == 0) => pn(ol.tail, pl)
case _ => pn(ol.tail, ol.head :: pl)
}
pn(ol, List(2)).reverse
}