Drop every Nth element from a Scala Array - scala

My requirement is to drop every Nth element from a Scala Array (pls note every Nth element). I wrote the below method which does the job. Since, I am new to Scala, I couldn't avoid the Java hangover. Is there a simpler or more efficient alternative?
def DropNthItem(a: Array[String], n: Int): Array[String] = {
val in = a.indices.filter(_ % n != 0)
val ab: ArrayBuffer[String] = ArrayBuffer()
for ( i <- in)
ab += a(i-1)
return ab.toArray
}

You made a good start. Consider this simplification.
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.indices.filter(x => (x+1) % n != 0).map(a).toArray

How about something like this?
arr.grouped(n).flatMap(_.take(n-1)).toArray

You can do this in two steps functionally using zipWithIndex to get an array of elements tupled with their indices, and then collect to build a new array consisting of only elements that have indices that aren't 0 = i % n.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] =
arr.zipWithIndex.collect { case (a, i) if (i + 1) % n != 0 => a }

This will make it
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.zipWithIndex.filter(_._2 % n != 0).map(_._1)

If you're looking for performance (since you're using an ArrayBuffer), you might as well track the index with a var, manually increment it, and check it with an if to filter out n-multiple-indexed values.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
var i = 0
for(a <- arr) {
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
It's faster still if we traverse the original array as an iterator using a while loop.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
val it = arr.iterator
var i = 0
while(it.hasNext) {
val a = it.next
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}

I'd go with something like this;
def dropEvery[A](arr: Seq[A], n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
// example: dropEvery(1 to 100, 3)
// res0: Seq[Int] = List(1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 100)
This is efficient since it requires a single pass over the array and removes every nth element from it – I believe that is easy to see.
The first case matches when idx == n - 1 and ignores the element at that index, and passes over the acc and resets the count to 0 for the next element.
If the first case doesn't match, it adds the element to the end of the acc and increments the count by 1.
Since you're willing to get rid of the Java hangover, you might want to use implicit classes to use this in a very nice way:
implicit class MoreFuncs[A](arr: Seq[A]) {
def dropEvery(n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
}
// example: (1 to 100 dropEvery 1) == Nil (: true)

Related

Sums of different lists using recursion

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)
}

Cumulative sum without var scala [duplicate]

I've got a List of days in the month:
val days = List(31, 28, 31, ...)
I need to return a List with the cumulative sum of days:
val cumDays = List(31, 59, 90)
I've thought of using the fold operator:
(0 /: days)(_ + _)
but this will only return the final result (365), whereas I need the list of intermediate results.
Anyway I can do that elegantly?
Scala 2.8 has the methods scanLeft and scanRight which do exactly that.
For 2.7 you can define your own scanLeft like this:
def scanLeft[a,b](xs:Iterable[a])(s:b)(f : (b,a) => b) =
xs.foldLeft(List(s))( (acc,x) => f(acc(0), x) :: acc).reverse
And then use it like this:
scala> scanLeft(List(1,2,3))(0)(_+_)
res1: List[Int] = List(0, 1, 3, 6)
I'm not sure why everybody seems to insist on using some kind of folding, while you basically want to map the values to the cumulated values...
val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
val cumulated = daysInMonths.map{var s = 0; d => {s += d; s}}
//--> List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
You can simply perform it:
daysInMonths.foldLeft((0, List[Int]()))
{(acu,i)=>(i+acu._1, i+acu._1 :: acu._2)}._2.reverse
Fold into a list instead of an integer. Use pair (partial list with the accumulated values, accumulator with the last sum) as state in the fold.
Fold your list into a new list. On each iteration, append a value which is the sum of the head + the next input. Then reverse the entire thing.
scala> val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
daysInMonths: List[Int] = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
scala> daysInMonths.foldLeft(Nil: List[Int]) { (acc,next) =>
| acc.firstOption.map(_+next).getOrElse(next) :: acc
| }.reverse
res1: List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
You can also create a monoid class that concatenates two lists while adding to the second one the last value from the first. No mutables and no folds involved:
case class CumSum(v: List[Int]) { def +(o: CumSum) = CumSum(v ::: (o.v map (_ + v.last))) }
defined class CumSum
scala> List(1,2,3,4,5,6) map {v => CumSum(List(v))} reduce (_ + _)
res27: CumSum = CumSum(List(1, 3, 6, 10, 15, 21))
For any:
val s:Seq[Int] = ...
You can use one of those:
s.tail.scanLeft(s.head)(_ + _)
s.scanLeft(0)(_ + _).tail
or folds proposed in other answers but...
be aware that Landei's solution is tricky and you should avoid it.
BE AWARE
s.map { var s = 0; d => {s += d; s}}
//works as long `s` is strict collection
val s2:Seq[Int] = s.view //still seen as Seq[Int]
s2.map { var s = 0; d => {s += d; s}}
//makes really weird things!
//Each value'll be different whenever you'll access it!
I should warn about this as a comment below Landei's answer but I couldn't :(.
Works on 2.7.7:
def stepSum (sums: List [Int], steps: List [Int]) : List [Int] = steps match {
case Nil => sums.reverse.tail
case x :: xs => stepSum (sums.head + x :: sums, steps.tail) }
days
res10: List[Int] = List(31, 28, 31, 30, 31)
stepSum (List (0), days)
res11: List[Int] = List(31, 59, 90, 120, 151)

Create groups of sequences whose element-wise difference is 1 in Scala?

We have the following sequence of numbers: [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]. We need to group this sequence according to difference between the neighboring values such that difference of values in each group would be equal to 1 if group size is > 1.
In Python, I would write something like:
outliers = [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]
chains = [[i for i in list(map(itemgetter(1), g))]
for _, g in itertools.groupby(enumerate(outliers),
lambda x: x[0]-x[1])]
# [[19], [23, 24], [31], [126, 127], [155], [159, 160, 161]]
Pretty neat. But how can this be done in Scala without falling back to loops with conditions? I have been trying to do something with zipWithIndex and groupBy methods by so far to no avail :(
You can fold over the sequence, building the result as you go.
outliers.foldRight(List.empty[List[Int]]) {case (n, acc) =>
if (acc.isEmpty) List(List(n))
else if (acc(0)(0) == n+1) (n :: acc.head) :: acc.tail
else List(n) :: acc
}
//res0: List[List[Int]] = List(List(19), List(23, 24), List(31), List(126, 127), List(155), List(159, 160, 161))
Not sure if recursion can match with your conditions but it at last O(n).
def rec(source: List[Int], temp: List[Int], acc: List[List[Int]]): List[List[Int]] = source match {
case Nil => acc
case x :: xs => {
if (xs.nonEmpty && xs.head - x == 1) rec(xs, temp :+ x, acc)
else rec(xs, List(), acc :+ (temp :+ x))
}
}
val outliers = List(19, 23, 24, 31, 126, 127, 155, 159, 160, 161)
rec(outliers, List[Int](), List[List[Int]]())

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
}