I've been trying to finish this scala code that uses a list to output the summation of all positive integers in the list.. I got it working except for having it only work for positive numbers. but i cant get it to only output the positive numbers. I have 2 versions that ive been trying to get to work, i thought maybe it would be easier wit cases, but i ended up running into the same problem. I've been trying if statements with xs<0 , but those don't work, and i cant get the filter to work with the fold. any suggestions with how to handle this?
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0)
xs.foldLeft(0) { _ + _ }
}
def sum2(xs: List[Int]): Int = xs match {
case Nil => 0
case y :: ys => y + sum(ys)
}
xs is an immutable List[Int], which means you are not just modifying the same xs value and returning it.
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0) // This is a pure expression and effectively does nothing
xs.foldLeft(0) { _ + _ } // This is the value that is returned, modifying the *original* `xs` parameter
}
What you need to do is chain the functions together, to operate on the same value.
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0).foldLeft(0) { _ + _ }
}
The type check isn't necessary here, so it can be shorted:
def sum(xs: List[Int]): Int = xs.filter(_ > 0).foldLeft(0)(_ + _)
There is also a sum method on List that does the same thing as your foldLeft.
def sum(xs: List[Int]): Int = xs.filter(_ > 0).sum
List(1, -2, 3).filter(_ > 0).sum // 4
or in a single pass
List(1, -2, 3).foldLeft(0){(acc, i) => if (i > 0) acc + i else acc } //4
Your 1st version is almost right. Remember that filter method doesn't have side effects, so just try this small change:
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0).foldLeft(0) { _ + _ }
}
Or simpler version:
def sum(xs: List[Int]): Int = {
xs.filter(_ > 0).sum
}
i ended up trying this , which i think is right. based on the suggestions
val f = xs.filter((x: Int) => x > 0)
f.foldLeft(0) { _ + _ }
Related
I need to write a recursive function that would return a corresponding integer from the given list. For example, list1 = List(2,3,1,7,5)
fromList(list1) would return 57132
This is what I have.
def fromList(list1: List[Int]): Int = {
val num1 = list1.head
val num2 = fromList(list1.tail)
if (list1.isEmpty) num1
else num1 + num2
}
I'm able to solve this if I use power operation but this operation is limited.
Something like this?
def fromList(list1: List[Int]): Int =
list1.reverse.fold(0)(10 * _ + _)
fromList(List(2,3,6)) //res0: Int = 632
Can also be done with foldRight().
def fromList(list1: List[Int]): Int =
list1.foldRight(0)(_ + _ * 10)
If recursion is required...
#annotation.tailrec
def fromList(list1: List[Int], acc:Int = 0): Int =
if (list1.isEmpty) acc
else fromList(list1.init, 10*acc + list1.last)
fromList(List(2,3,6,1)) //res0: Int = 1632
Or the slightly more verbose but likely more efficient...
def fromList(list1: List[Int]): Int = {
#annotation.tailrec
def loop(lst: List[Int], acc:Int = 0):Int = lst match {
case hd::tl => loop(tl, 10*acc + hd)
case _ => acc
}
loop(list1.reverse, 0)
}
fromList(List(7,3,6,4)) //res0: Int = 4637
There are 2 major problems with your original design.
1st - Both list1.head and list1.tail are impossible if list1.isEmpty. So you need to test for that before decomposing the List.
2nd - You need to adjust the intermediate results before adding the current digit.
//recursive but not tail-recursive
def fromList(list1: List[Int]): Int =
if (list1.isEmpty) 0
else 10 * fromList(list1.tail) + list1.head
#jwvh solution is recursive(tail) if you might want a non tail recursive though with a good chance of a stack overflow for large values then
def solution (list : List[Int]): Int = {
def recursive(list1: List[Int]): Int= {
list1 match {
case head :: tail => head * scala.math.pow(10, list1.length-1).toInt + recursive(tail)
case Nil => 0
}
}
recursive(list.reverse)
}
Not recursive, but does the job :)
list1.reverse.mkString("").toInt
The aim of the method is to take elements in a list until a limit is reached.
e.g.
I've come up with 2 different implementations
def take(l: List[Int], limit: Int): List[Int] = {
var sum = 0
l.takeWhile { e =>
sum += e
sum <= limit
}
}
It is straightforward, but a mutable state is used.
def take(l: List[Int], limit: Int): List[Int] = {
val summed = l.toStream.scanLeft(0) { case (e, sum) => sum + e }
l.take(summed.indexWhere(_ > limit) - 1)
}
It seems cleaner, but it's more verbose and perhaps less memory efficient because a stream is needed.
Is there a better way ?
You could also do that in a single pass with a fold:
def take(l: List[Int], limit: Int): List[Int] =
l.fold((List.empty[Int], 0)) { case ((res, acc), next) =>
if (acc + next > limit)
(res, limit)
else
(next :: res, next + acc)
}
Because the standard lists aren't lazy, and neither is fold, this will always traverse the entire list. One alternative would be to use cats' iteratorFoldM instead for an implementation that short circuits once the limit is reached.
You could also write the short circuiting fold directly using tail recursion, something along those lines:
def take(l: List[Int], limit: Int): List[Int] = {
#annotation.tailrec
def take0(list: List[Int], accList: List[Int], accSum: Int) : List[Int] =
list match {
case h :: t if accSum + h < limit =>
take0(t, h :: accList, h + accSum)
case _ => accList
}
take0(l, Nil, 0).reverse
}
Note that this second solution might be faster, but also less elegant as it requires additional effort to prove that the implementation terminates, something obvious when using a fold.
The first way is perfectly fine as the result of your function is still perfectly immutable.
On a side note, this is actually how many functions of the scala collection library are implemented, they create a mutable builder for efficiency and return an immutable collection out of it.
A functional way is to use recursive function and make sure it is stack safe.
If you just use basic scala:
import scala.annotation.tailrec
def take(l: List[Int], limit: Int) : List[Int] = {
#tailrec
def takeHelper(l:List[Int], limit:Int, r:List[Int]):List[Int] =
l match {
case h::t if (h <= limit ) => takeHelper(t, limit-h, r:+h)
case _ => r
}
takeHelper(l, limit, Nil)
}
If you can use scalaz Trampoline, it is a bit nicer:
import scalaz._
import scalaz.Scalaz._
import Free._
def take(l: List[Int], limit: Int): Trampoline[List[Int]] = {
l match {
case h :: t if (h <= limit) => suspend(take(t, limit - h)).map(h :: _)
case _ => return_(Nil)
}
}
println(take(List(1, 2, 3, 4, 0, 0, 1), 10).run)
println(take(List.fill(10000)(1), 100000000).run)
if you want to extend your own customize way, you could also use something like:
def custom(con: => Boolean)(i: Int)(a: => List[Int])(body: => Unit): List[Int] = {
if (con) {
body
custom(con)(i + 1)(a)(body)
}
else {
a.slice(0, i)
}
}
then call it like this:
var j = 100
val t = customTake(j > 80)(0)((0 to 99).toList) {
j -= 1
}
println(t)
I think your second version is already pretty good. You might tweak it a little, like this:
val sums = l.toStream.scanLeft(0){_ + _} drop 1
l zip sums takeWhile {_._2 <= limit} map (_._1)
This way you aren't dealing with indices, which is usually a little easier to follow.
The following logic identifies the combination of integers summing to n that produces the maximum product:
def bestProd(n: Int) = {
type AType = (Vector[Int], Long)
import annotation._
// #tailrec (umm .. nope ..)
def bestProd0(n: Int, accum : AType): AType = {
if (n<=1) accum
else {
var cmax = accum
for (k <- 2 to n) {
val tmpacc = bestProd0(n-k, (accum._1 :+ k, accum._2 * k))
if (tmpacc._2 > cmax._2) {
cmax = tmpacc
}
}
cmax
}
}
bestProd0(n, (Vector(), 1))
}
This code does work:
scala> bestProd(11)
res22: (Vector[Int], Long) = (Vector(2, 3, 3, 3),54)
Now it was not a surprise to me that #tailrec did not work. After all the recursive invocation is not in the tail position. Is is possible to reformulate the for loop to instead do a proper single-call to achieve the tail recursion?
I don't think it's possible if you're trying to stick close to the stated algorithm. Rethinking the approach you could do something like this.
import scala.annotation.tailrec
def bestProd1(n: Int) = {
#tailrec
def nums(acc: Vector[Int]): Vector[Int] = {
if (acc.head > 4)
nums( (acc.head - 3) +: 3 +: acc.tail )
else
acc
}
val result = nums( Vector(n) )
(result, result.product)
}
It comes up with the same results (as far as I can tell) except for I don't split 4 into 2,2.
I know of at least two styles to writing tail recursive functions. Take a sum function for example:
def sum1(xs: List[Int]): Int = {
def loop(xs: List[Int], acc: Int): Int = xs match {
case Nil => acc
case x :: xs1 => loop(xs1, acc + x)
}
loop(xs, 0)
}
vs
def sum2(xs: List[Int], acc: Int = 0): Int = xs match {
case Nil => acc
case x :: xs1 => sum2(xs1, x + acc)
}
I've noticed the first style (internal loop function) much more commonly than the second. Is there any reason to prefer it or is the difference just a matter of style?
There a couple of reasons to prefer the first notation.
Firstly, you define clearly to your reader what's the internal implementation from the external one.
Secondly, in your example the seed value is a pretty simple one that you can put straight as a default argument, but your seed value may be a very complicated-to-compute object that requires a longer init than default. Should this init for example require to be done asynchronously, you definitely want to put it out of your default value and manage with Futures or w/e.
Lastly, as Didier mentioned, the type of sum1 is a function from List[Int] -> Int (which makes sense), while the type of sum2 is a function from (List[Int], Int) -> Int which is less meaningful. Also, this implies that it's easier to pass sum1 around than sum2. For example, if you have an object that encapsulates a list of Int's and you want to provide synthesizer functions over it you can do (pseudocode, i dont have a repl to write it properly now):
class MyFancyList[T](val seed: List[T]) = {
type SyntFunction = (List[T] => Any)
var functions = Set[SyntFunction]
def addFunction(f: SyntFunction) = functions += f
def computeAll = {
for {
f <- functions
}
yield {
f(seed)
}
}
}
And you can do:
def concatStrings(list:List[Int]) = {
val listOfStrings = for {
n <- list
}
yield {
n+""
}
listOfStrings.mkString
}
val x = MyFancyList(List(1, 2, 3))
x.addFunction(sum1)
x.addFunction(concatStrings)
x.computeAll == List(6, "123")
but you can't add sum2 (not as easily at least)
I had a simple task to find combination which occurs most often when we drop 4 cubic dices an remove one with least points.
So, the question is: are there any Scala core classes to generate streams of cartesian products in Scala? When not - how to implement it in the most simple and effective way?
Here is the code and comparison with naive implementation in Scala:
object D extends App {
def dropLowest(a: List[Int]) = {
a diff List(a.min)
}
def cartesian(to: Int, times: Int): Stream[List[Int]] = {
def stream(x: List[Int]): Stream[List[Int]] = {
if (hasNext(x)) x #:: stream(next(x)) else Stream(x)
}
def hasNext(x: List[Int]) = x.exists(n => n < to)
def next(x: List[Int]) = {
def add(current: List[Int]): List[Int] = {
if (current.head == to) 1 :: add(current.tail) else current.head + 1 :: current.tail // here is a possible bug when we get maximal value, don't reuse this method
}
add(x.reverse).reverse
}
stream(Range(0, times).map(t => 1).toList)
}
def getResult(list: Stream[List[Int]]) = {
list.map(t => dropLowest(t).sum).groupBy(t => t).map(t => (t._1, t._2.size)).toMap
}
val list1 = cartesian(6, 4)
val list = for (i <- Range(1, 7); j <- Range(1,7); k <- Range(1, 7); l <- Range(1, 7)) yield List(i, j, k, l)
println(getResult(list1))
println(getResult(list.toStream) equals getResult(list1))
}
Thanks in advance
I think you can simplify your code by using flatMap :
val stream = (1 to 6).toStream
def cartesian(times: Int): Stream[Seq[Int]] = {
if (times == 0) {
Stream(Seq())
} else {
stream.flatMap { i => cartesian(times - 1).map(i +: _) }
}
}
Maybe a little bit more efficient (memory-wise) would be using Iterators instead:
val pool = (1 to 6)
def cartesian(times: Int): Iterator[Seq[Int]] = {
if (times == 0) {
Iterator(Seq())
} else {
pool.iterator.flatMap { i => cartesian(times - 1).map(i +: _) }
}
}
or even more concise by replacing the recursive calls by a fold :
def cartesian[A](list: Seq[Seq[A]]): Iterator[Seq[A]] =
list.foldLeft(Iterator(Seq[A]())) {
case (acc, l) => acc.flatMap(i => l.map(_ +: i))
}
and then:
cartesian(Seq.fill(4)(1 to 6)).map(dropLowest).toSeq.groupBy(i => i.sorted).mapValues(_.size).toSeq.sortBy(_._2).foreach(println)
(Note that you cannot use groupBy on Iterators, so Streams or even Lists are the way to go whatever to be; above code still valid since toSeq on an Iterator actually returns a lazy Stream).
If you are considering stats on the sums of dice instead of combinations, you can update the dropLowest fonction :
def dropLowest(l: Seq[Int]) = l.sum - l.min