Order of parameters to foldright and foldleft in scala - scala

Why does the foldLeft take
f: (B, A) => B
and foldRight take
f: (A, B) => B
foldLeft could have been written to take f: (A, B) => B.
I am trying to understand the reasoning for the difference in the order of parameters.

It's supposed to show you the direction of the aggregation. FoldLeft aggregates from left to right, so you can imagine the accumulator B as bunching up stuff on the left side as it approaches each A:
If you have something like:
Vector(1,2,3,4,5).foldLeft(0)((b,a) => b + a)
Then you get this behavior
B ...As...
---------------
(0), 1, 2, 3, 4, 5
(0+1), 2, 3, 4, 5
(0+1+2), 3, 4, 5
(0+1+2+3), 4, 5
(0+1+2+3+4), 5
(0+1+2+3+4+5)
FoldRight, on the other hand, aggregates things from the right side. So if you have something like:
Vector(1,2,3,4,5).foldRight(0)((a,b) => a + b)
Then you get this behavior
...As... B
-----------------
1, 2, 3, 4, 5 (0)
1, 2, 3, 4, (5+0)
1, 2, 3, (4+5+0)
1, 2, (3+4+5+0)
1, (2+3+4+5+0)
(1+2+3+4+5+0)

#dhg already provided a great answer. My example illustrates an interesting subtlety: namely, that sometimes the the order in which the initial
value is passed to the given function matters. So I figured I'd post this on the off chance someone
is interested in cases where foldRight can behave differently than foldLeft
with the same initial value, same function, and same input list.
Consider the exponentiation below:
def verbosePower(base:Double, exp:Double) = {
println(s"base=$base / exp=$exp") ;
math.pow(base, exp)
}
var X = List(2.0,3).foldLeft(1.0) (verbosePower)
System.out.println("x:" + X);
X = List(2.0,3).foldRight(1.0) (verbosePower)
System.out.println("x:" + X);
the output and result from foldLeft is:
base=1.0 / exp=2.0
base=1.0 / exp=3.0
X: Double = 1.0
the output and result from foldRight is:
base=3.0 / exp=1.0
base=2.0 / exp=3.0
X: Double = 8.0

Related

How to apply filter on list of _2 of tuples in Scala?

I want all the lists(the first element of below tuple) if second element is the powers of 2. I am new to Scala and stuck with syntax. Could anyone help me here I want to apply filter on below code to get below output.
Output:
List(1,3)
List(1,7)
List(3,5)
List(7,9)
input:
scala> a.toList.combinations(2).map(x => (x, x.sum)).foreach(println)
(List(1, 3),4)
(List(1, 5),6)
(List(1, 7),8)
(List(1, 9),10)
(List(3, 5),8)
(List(3, 7),10)
(List(3, 9),12)
(List(5, 7),12)
(List(5, 9),14)
(List(7, 9),16)
val tups = List((List(1, 3),4), (List(1, 5),6), (List(1, 7),8) ,
(List(1, 9),10), (List(3, 5),8), (List(3, 7),10),
(List(3, 9),12), (List(5, 7),12),
(List(5, 9),14), (List(7, 9),16))
Using fold:
tups.foldLeft(List[List[Int]]())((a, b) => if((b._2 & (b._2 - 1)) == 0) a :+ b._1 else a)
Using filter and map:
tups.filter(e => (e._2 & (e._2 - 1)) == 0).map(_._1)
x & (x - 1) == 0 is the bitwise operation that checks if a number is a power of 2
For a more detailed explanation of the syntax, documentation for fold and other List operations can be found here
For
val xs = List(1,3,5,7,9)
another approach that incorporates the generation of input and corresponding filtering includes
import scala.math.log
// testPower true if log is integral value
// log_base n = log_e n / log_e base
def testPower(n: Int, base: Int = 2): Boolean = {
val lg = log(n) / log(base)
lg.toInt == lg
}
xs.combinations(2).filter(ys => testPower(ys.sum)).toList
The test provided in #sinanspd answer is more succinct as well as more efficient; the test here generalises to any power in addition to 2. This solution works for any combination size as it sums up the entire combination (sub)list.
You can use the fact that the binary representation of an element that is the power of 2, has only 1 bit which is 1, and all. others are 0's. Then use toBinaryString method:
val xs = List(1, 3, 5, 7, 9).combinations(2).map(x => (x, x.sum)).toList
val result = xs.filter(_._2.toBinaryString.count(_ == '1') == 1).map(_._1)
Code run at Scastie.

Scala: subtract index of odd values

For a practical exercise I need to define a function that basically changes the index of every value in an odd index in a list, so that I would get this:
changePairs(List(1,2,3,4,5,6,7,8,9,10,11))
//> res62: List[Int] = List(2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 11)
changePairs(List(2,2,30,4,50,6,7,80,9,100))
//> res63: List[Int] = List(2, 2, 4, 30, 6, 50, 80, 7, 100, 9)
So basically I need to swap the places of each odd-even pair, and in case I'm left with a single odd element at the last index (11 in the first example), I leave it as it is.
I have this but it's definitely not working, and I'm not really sure why.
def changePairs(a: List[Int]) = a.zipWithIndex.map {
case (s,i) => if (i % 2 != 0) a.patch(i,Seq(s),1); a.patch(i-2,Seq(s),0);
}
Here's one way:
def changePairs(a: List[Int]) = a.grouped(2).flatMap {
case List(a, b) => List(b, a)
case a => a
}.toList
changePairs(List(1, 2, 3, 4, 5, 6, 7)) // List(2, 1, 4, 3, 6, 5, 7)
Main idea that gets you going is once you think of grouping the list into sublists of two elements, which is what grouped(2) does. From then on it's an easy ride - describe two cases, one with two elements (in that case we flip them) and one with only one element, such as 7 in my example, in which case we just leave it be. We use flatMap to flatten the resulting list of 2-element lists into one big list, and we do .toList to get out of an iterator that we got from grouped.
EDIT:
I now saw a.grouped(2).map(_.reverse).flatten.toList in the comments. Yeah, that works too, it's the same as this but much less verbose since instead of "manually" swapping the elements, we just do a reverse on each sublist.
You could also use recursion and pattern matching. This is efficient as you are only going through the list once:
def changePairs(l: List[Int]): List[Int] = {
l match {
case a :: b :: tail => b :: a :: changePairs(tail)
case _ => Nil
}
}

Is there a "for" syntax for flatmap?

Is there a "for" syntax for
c flatmap ( x => d flatmap (y => f(x,y) ) )
?
Because I've used Haskell in the past, I keep expecting the "for" syntax in Scala to mimic the "do" syntax of Haskell. This is probably an unrealistic expectation. In Haskell which I could write
do x <- c
y <- d
f(x, y)
You could also map the last result on itself.
Using the same example as dhg:
val c = 1 to 3
val d = 4 to 6
def f(x: Int, y: Int) = Vector(x,y)
for {
x <- c
y <- d
z <- f(x, y)
} yield z
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)
Which corresponds to:
c flatMap ( x => d flatMap (y => f(x,y) map (identity) ) )
You can just flatten the result:
val c = 1 to 3
val d = 4 to 6
def f(x: Int, y: Int) = Vector(x,y)
c flatMap ( x => d flatMap (y => f(x,y) ) )
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)
(for { x <- c; y <- d } yield f(x,y)).flatten
// Vector(1, 4, 1, 5, 1, 6, 2, 4, 2, 5, 2, 6, 3, 4, 3, 5, 3, 6)
Presumably this is a much less frequently used case since it is necessarily less common that the output of the for is flattenable. And sticking .flatten on the end is pretty easy, so having a special syntax for it seems unnecessarily complicated.
Flattening may impact performance but i think scalac is clever enough to encode
for {
x <- c
y <- d
z <- f(x,y)
} yield z
into
c flatMap { x => d flatMap { y => f(x,y) } }
This is annoying that the 'for' syntax is not as convenient as the 'do'-notation (writing _ <- someExpression instead of just someExpression in a for feels my heart with sadness).

Reverse list of n elements

i was given this problem and i thought I had it figured out , but i was told i had it wrong. the question was,. Given a list xs, reverse the first n elements. I guess im not understanding what the question was asking , i thought we take an Int n , and return the first n elements in front of that int n in reverse.
def nthRev[T](n: Int,xs: List[T]): List[T] = xs match {
case List() => List()
case head :: rest => (head::rest.take(n)).reverse
}
so, the output is
nthRev(3,List(1, 2, 3, 4, 5))
returns
List(4, 3, 2, 1)
but apparently its wrong, can anyone explain what the question is asking for?
The way I interpret your question "Given a list xs, reverse the first n elements." and the example
nthRev(3,List(1, 2, 3, 4, 5))
I would expect it to reverse the first 3 elements, but then leave the rest of the list:
List(3, 2, 1, 4, 5)
When the question says "first n elements" it is saying to replace "n" with the number given as the first argument in your example "3", to give "first 3 elements". The 3 has nothing to do with the element in the list. Changing your example:
nthRev(3,List(10,11,12,13,14)
would return
List(12,11,10,13,14)
I think it means you're supposed to return a new list that has the same elements of the original list, but with the first n elements reversed.
def nthRev[T](n: Int, xs: List[T]): List[T] =
xs.splitAt(n) match { case (a, b) => a.reverse ::: b }
nthRev(3, (1 to 5).toList) // List(3, 2, 1, 4, 5)
I would go with simple standard API. Have a look at the drop function explained in this post: Skip first N elements in scala iterable
def reverseAtN[a](n: Int, list: List[a]): List[a] =
List.concat(x.take(n).reverse, x.drop(n))

Scala: Producing the intermediate results of a fold

I've come across the problem of maintaining a state throughout a map operation several times. Imagine the following task:
Given a List[Int], map each element to the sum of all preceding elements and itself.
So 1,2,3 becomes 1, 1+2, 1+2+3.
One solution I've come up with is:
scala> val a = 1 to 5
a: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5)
scala> a.foldLeft(List(0)){ case (l,i) => (l.head + i) :: l }.reverse
res3: List[Int] = List(0, 1, 3, 6, 10, 15)
But somehow I feel that there has to be a simpler solution.
You're trying to compute the sequence of partial sums.
The general operation for computing such accumulations is not fold but scan, though scan is expressible through fold in the way you showed (and fold is actually the last element of the list produced by scan).
scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
#Dario gave the answer, but just to add that the scala library provides scanLeft:
scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
The scan answers are the best ones, but it's worth noting that one can make the fold look nicer and/or be shorter than in your question. First, you don't need to use pattern matching:
a.foldLeft(List(0)){ (l,i) => (l.head + i) :: l }.reverse
Second, note that foldLeft has an abbreviation:
(List(0) /: a){ (l,i) => (l.head + i) :: l }.reverse
Third, note that you can, if you want, use a collection that can append efficiently so that you don't need to reverse:
(Vector(0) /: a){ (v,i) => v :+ (v.last + i) }
So while this isn't nearly as compact as scanLeft:
a.scanLeft(0)(_ + _)
it's still not too bad.
I like to fold around just like everybody else, but a less FP answer is very concise and readable:
a.map{var v=0; x=>{v+=x; v}}