I have the following function which I have checked about a dozen times, and should work exactly as I want, but it ends up with the wrong result. Can anyone point out what is wrong with this function?
Note: I'm printing out the list that is being passed in recursive calls; and the list is exactly as I expect it to be. But the variable called result that accumulates the result does not contain the correct permutations at the end. Also, I synchronized the access to result variable, but that did NOT fix the problem; so, I don't think synchronization is a problem. The code can be copied and run as is.
import collection.mutable._
def permute(list:List[Int], result:StringBuilder):Unit =
{
val len = list.size
if (len == 0) (result.append("|"))
else
{
for (i <- 0 until len )
{
println("========" + list + "===========")
result.append( list(i) )
if (i != len -1)
{
//println("Adding comma since i is: " + i)
result.append(", ")
}
//println("******** Reslut is:" + result + "***********")
permute( (sublist(list, i) ), result)
}
}
// This function removes just the ith item, and returns the new list.
def sublist (list:List[Int], i:Int): List[Int] =
{
var sub:ListBuffer[Int] = (list.map(x => x)).to[ListBuffer]
sub.remove(i)
return sub.toList
}
}
var res = new StringBuilder("")
permute(List(1,2,3), res)
println(res)
The output is:
========List(1, 2, 3)===========
========List(2, 3)===========
========List(3)===========
========List(2, 3)===========
========List(2)===========
========List(1, 2, 3)===========
========List(1, 3)===========
========List(3)===========
========List(1, 3)===========
========List(1)===========
========List(1, 2, 3)===========
========List(1, 2)===========
========List(2)===========
========List(1, 2)===========
========List(1)===========
**1, 2, 3|32|2, 1, 3|31|31, 2|21|**
I think Dici's solution is good, but kind of cryptic. I think the following code is much more clear:
def permutations(list: List[Int]): List[List[Int]] = list match
{
case Nil | _::Nil => List(list)
case _ =>(
for (i <- list.indices.toList) yield
{
val (beforeElem, afterElem) = list.splitAt(i)
val element = afterElem.head
val subperm = permutations (beforeElem ++ afterElem.tail)
subperm.map(element:: _)
}
).flatten
}
val result = permutations(List (1,2,3,4,5) )
println(result.mkString("\n") )
The output will be:
List(1, 2, 3)
List(1, 3, 2)
List(2, 1, 3)
List(2, 3, 1)
List(3, 1, 2)
List(3, 2, 1)
There are various problems with your approach, the main one being that you don't actually implement the recurrence relation between the permutations of n elements and the permutations of n + 1 elements, which is that you can take all permutations of n elements and insert the n + 1th element at every position of every permutation of n elements to get all the permutations of n + 1 elements.
One way to do it, more Scalatically, is:
def sortedPermutations(list: List[Int]): List[List[Int]] = list match {
case Nil | _ :: Nil => List(list)
case _ => list.indices.flatMap(i => list.splitAt(i) match {
case (head, t :: tail) => sortedPermutations(head ::: tail).map(t :: _)
}).toList
}
println(sortedPermutations(List(1, 2, 3)).map(_.mkString(",")).mkString("|"))
Output:
1,2,3|1,3,2|2,1,3|2,3,1|3,1,2|3,2,1
Note that this is very inefficient though, because of all the list concatenations. An efficient solution would be tail-recursive or iterative. I'll post that a bit later for you.
Related
Say I have a List. I filter it first on some condition. Now I want to pass the initial value from this filtered array to foldLeft all while chaining both together. Is there a way to do that?
For example:
scala> val numbers = List(5, 4, 8, 6, 2)
val numbers: List[Int] = List(5, 4, 8, 6, 2)
scala> numbers.filter(_ % 2 == 0).foldLeft(numbers(0)) { // this is obviously incorrect since numbers(0) is the value at index 0 of the original array not the filtered array
| (z, i) => z + i
| }
val res88: Int = 25
You could just pattern match on the result of filtering to get the first element of list (head) and the rest (tail):
val numbers = List(5, 4, 8, 6, 2)
val result = numbers.filter(_ % 2 == 0) match {
case head :: tail => tail.foldLeft(head) {
(z, i) => z + i
}
// here you need to handle the case, when after filtering there are no elements, in this case, I just return 0
case Nil => 0
}
You could also just use reduce:
numbers.filter(_ % 100 == 0).reduce {
(z, i) => z + i
}
but it will throw an exception in case after filtering the list is empty.
I have a sequence Seq[T] and I want to do partial reduce. For example for a Seq[Int] I want to get Seq[Int] consisting of the longest partial sums of monotonic regions. For example:
val s = Seq(1, 2, 4, 3, 2, -1, 0, 6, 8)
groupMonotionic(s) = Seq(1 + 2 + 4, 3 + 2 + (-1), 0 + 6 + 8)
I was looking for some method like conditional fold with the signature fold(z: B)((B, T) => B, (T, T) => Boolean) where the predicate states for where to terminate current sum aggregation, but it seems there is no something like that in the subtrait hierarchy of Seq.
What would be a solution using Scala Collection API and without using mutable variables?
Here is one way amongst many to do this (using Scala 2.13's List#unfold):
// val items = Seq(1, 2, 4, 3, 2, -1, 0, 6, 8)
items match {
case first :: _ :: _ => // If there are more than 2 items
List
.unfold(items.sliding(2).toList) { // We slid items to work on pairs of consecutive items
case Nil => // No more items to unfold
None // None signifies the end of the unfold
case rest # Seq(a, b) :: _ => // We span based on the sign of a-b
Some(rest.span(x => (x.head - x.last).signum == (a-b).signum))
}
.map(_.map(_.last)) // back from slided pairs
match { case head :: rest => (first :: head) :: rest }
case _ => // If there is 0 or 1 item
items.map(List(_))
}
// List(List(1, 2, 4), List(3, 2, -1), List(0, 6, 8))
List.unfold iterates as long as the unfolding function provides Some. It starts with an initial state which is the list of items to unfold. At each iteration, we span the state (remaining elements to unfold) based on the sign of the heading two elements difference. The unfolded elements are heading items sharing the same monotony and the unfolding state becomes the other remaining elements.
List#span splits a list into a tuple whose first part contains elements matching the predicate applied until the predicate stops being valid. The second part of the tuple contains the rest of the elements. Which fits perfectly the expected return type of List.unfold's unfolding function, which is Option[(A, S)] (In this case Option[(List[Int], List[Int])]).
Int.signum returns -1, 0 or 1 depending on the sign of the integer it's applied on.
Note that the first item has to be put back in the result as it hasn't an ancestor determining its signum (match { case head :: rest => (first :: head) :: rest }).
To apply the reducing function (in this case a sum), we can map the final result: .map(_.sum)
Works in Scala 2.13+ with cats
import scala.util.chaining._
import cats.data._
import cats.implicits._
val s = List(1, 2, 4, 3, 2, -1, 0, 6, 8)
def isLocalExtrema(a: List[Int]) =
a.max == a(1) || a.min == a(1)
implicit class ListOps[T](ls: List[T]) {
def multiSpanUntil(f: T => Boolean): List[List[T]] = ls.span(f) match {
case (h, Nil) => List(h)
case (h, t) => (h ::: t.take(1)) :: t.tail.multiSpanUntil(f)
}
}
def groupMonotionic(groups: List[Int]) = groups match {
case Nil => Nil
case x if x.length < 3 => List(groups.sum)
case _ =>
groups
.sliding(3).toList
.map(isLocalExtrema)
.pipe(false :: _ ::: List(false))
.zip(groups)
.multiSpanUntil(!_._1)
.pipe(Nested.apply)
.map(_._2)
.value
.map(_.sum)
}
println(groupMonotionic(s))
//List(7, 4, 14)
Here's one way using foldLeft to traverse the numeric list with a Tuple3 accumulator (listOfLists, prevElem, prevTrend) that stores the previous element and previous trend to conditionally assemble a list of lists in the current iteration:
val list = List(1, 2, 4, 3, 2, -1, 0, 6, 8)
val isUpward = (a: Int, b: Int) => a < b
val initTrend = isUpward(list.head, list.tail.head)
val monotonicLists = list.foldLeft( (List[List[Int]](), list.head, initTrend) ){
case ((lol, prev, prevTrend), curr) =>
val currTrend = isUpward(curr, prev)
if (currTrend == prevTrend)
((curr :: lol.head) :: lol.tail , curr, currTrend)
else
(List(curr) :: lol , curr, currTrend)
}._1.reverse.map(_.reverse)
// monotonicLists: List[List[Int]] = List(List(1, 2, 4), List(3, 2, -1), List(0, 6, 8))
To sum the individual nested lists:
monotonicLists.map(_.sum)
// res1: List[Int] = List(7, 4, 14)
Trying to remove the first element of a list if it is zero (not really, but for the purpose of an example).
Given a list:
val ns = List(0, 1, 2)
Deleting the first zero could be done by dropping the first matches for zero:
List(0, 1, 2).dropWhile(_ == 0)
res1: List[Int] = List(1, 2)
Or you could delete everything that's not a zero.
List(0, 1, 2).filter(_ > 0)
res2: List[Int] = List(1, 2)
The problem with these is when the list has multiple zeroes. The previous solutions don't work, because they delete too many zeroes:
List(0, 0, 1, 2, 0).filter(_ > 0)
res3: List[Int] = List(1, 2)
List(0, 0, 1, 2, 0).dropWhile(_ == 0)
res4: List[Int] = List(1, 2, 0)
Is there an existing function for this?
I also think pattern matching is the best option for readability and performance (I tested and the pattern matching code from OP actually performs better than simple if ... else ....).
List(0, 0, 1, 2, 0) match {
case 0 :: xs => xs
case xs => xs
}
res10: List[Int] = List(0, 1, 2, 0)
And, no, there's no simple built in function for this.
If you only want to drop the first element conditionally, then as jwvh commented, an if/else comprehension is probably the simplest:
if (ns.nonEmpty && ns.head == 0) {
ns.tail
} else {
ns
}
You could then of course wrap this into a function.
You could look for a sequence of one zero, and drop it:
if (ns.startsWith(List(0))) {
ns.drop(1)
} else {
ns
}
Also known as returning the tail:
if (ns.startsWith(List(0))) {
ns.tail
} else {
ns
}
A neat generalized solution would be explicitly add information to your elements.
Example:
How to drop by condition and limit the amount from left to right?
List(0,0,0,1,2,2,3).zipWithIndex.dropWhile({case (elem,index) => elem == 0 && index < 2})
Result:
res0: List[(Int, Int)] = List((0,2), (1,3), (2,4), (2,5), (3,6))
You can get your previous representation with:
res0.map.{_._1}
To do everything in N, you can use lazy evaluation + the force method.
List(0,0,0,1,2,2,3).view.zipWithIndex.dropWhile({case (elem,index) => elem == 0 && index < 2}).map {_._1}.force
This will basically do all the operations on your initial collection in one single iteration. See scaladoc for more info to Scala views..
Modifying your condition on the right size you can choose how far the drop condition will reach inside your collection.
Here's a generalised variant (drop up to K elements matching the predicate) which does not process the rest of the list
def dropWhileLimit[A](xs: List[A], f: A => Boolean, k: Int): List[A] = {
if (k <= 0 || xs.isEmpty || !f(xs.head)) xs
else dropWhileLimit(xs.tail, f, k - 1)
}
and some test cases:
dropWhileLimit(List(0,1,2,3,4), { x:Int => x == 0}, 1)
//> res0: List[Int] = List(1, 2, 3, 4)
dropWhileLimit(List(0,1,2,3,4), { x:Int => x == 0}, 2)
//> res1: List[Int] = List(1, 2, 3, 4)
dropWhileLimit(List(0,0,0,0,0), { x:Int => x == 0}, 1)
//> res2: List[Int] = List(0, 0, 0, 0)
dropWhileLimit(List(0,0,0,0,0), { x:Int => x == 0}, 3)
//> res3: List[Int] = List(0, 0)
You can zip the list with an index:
ns.zipWithIndex.filter( x =>( x._1 != 0 || x._2 != 0)).map(_._1)
Here's a similar solution using dropWhile:
ns.zipWithIndex.dropWhile {
case (x, idx) => x == 0 && idx == 0
} map(_._1)
This could also be a for-comprehension
for {
(x, idx) <- ns.zipWithIndex
if (x != 0 || idx != 0) )
} yield {
x
}
But as Paul mentioned, it will unnecessarily iterate over the entire list.
That's a good option if you wanna drop the first element according to the filter but the value isn't in the first place.
def dropFirstElement( seq: Seq[Int], filterValue: Int ): Seq[Int] = {
seq.headOption match {
case None => seq
case Some( `filterValue` ) => seq.tail
case Some( value ) => value +: dropFirstElement( seq.tail, filterValue )
}
}
Given a List of Int and variable X of Int type . What is the best in Scala functional way to retain only those values in the List (starting from beginning of list) such that sum of list values is less than equal to variable.
This is pretty close to a one-liner:
def takeWhileLessThan(x: Int)(l: List[Int]): List[Int] =
l.scan(0)(_ + _).tail.zip(l).takeWhile(_._1 <= x).map(_._2)
Let's break that into smaller pieces.
First you use scan to create a list of cumulative sums. Here's how it works on a small example:
scala> List(1, 2, 3, 4).scan(0)(_ + _)
res0: List[Int] = List(0, 1, 3, 6, 10)
Note that the result includes the initial value, which is why we take the tail in our implementation.
scala> List(1, 2, 3, 4).scan(0)(_ + _).tail
res1: List[Int] = List(1, 3, 6, 10)
Now we zip the entire thing against the original list. Taking our example again, this looks like the following:
scala> List(1, 2, 3, 4).scan(0)(_ + _).tail.zip(List(1, 2, 3, 4))
res2: List[(Int, Int)] = List((1,1), (3,2), (6,3), (10,4))
Now we can use takeWhile to take as many values as we can from this list before the cumulative sum is greater than our target. Let's say our target is 5 in our example:
scala> res2.takeWhile(_._1 <= 5)
res3: List[(Int, Int)] = List((1,1), (3,2))
This is almost what we want—we just need to get rid of the cumulative sums:
scala> res2.takeWhile(_._1 <= 5).map(_._2)
res4: List[Int] = List(1, 2)
And we're done. It's worth noting that this isn't very efficient, since it computes the cumulative sums for the entire list, etc. The implementation could be optimized in various ways, but as it stands it's probably the simplest purely functional way to do this in Scala (and in most cases the performance won't be a problem, anyway).
In addition to Travis' answer (and for the sake of completeness), you can always implement these type of operations as a foldLeft:
def takeWhileLessThanOrEqualTo(maxSum: Int)(list: Seq[Int]): Seq[Int] = {
// Tuple3: the sum of elements so far; the accumulated list; have we went over x, or in other words are we finished yet
val startingState = (0, Seq.empty[Int], false)
val (_, accumulatedNumbers, _) = list.foldLeft(startingState) {
case ((sum, accumulator, finished), nextNumber) =>
if(!finished) {
if (sum + nextNumber > maxSum) (sum, accumulator, true) // We are over the sum limit, finish
else (sum + nextNumber, accumulator :+ nextNumber, false) // We are still under the limit, add it to the list and sum
} else (sum, accumulator, finished) // We are in a finished state, just keep iterating over the list
}
accumulatedNumbers
}
This only iterates over the list once, so it should be more efficient, but is more complicated and requires a bit of reading code to understand.
I will go with something like this, which is more functional and should be efficient.
def takeSumLessThan(x:Int,l:List[Int]): List[Int] = (x,l) match {
case (_ , List()) => List()
case (x, _) if x<= 0 => List()
case (x, lh :: lt) => lh :: takeSumLessThan(x-lh,lt)
}
Edit 1 : Adding tail recursion and implicit for shorter call notation
import scala.annotation.tailrec
implicit class MyList(l:List[Int]) {
def takeSumLessThan(x:Int) = {
#tailrec
def f(x:Int,l:List[Int],acc:List[Int]) : List[Int] = (x,l) match {
case (_,List()) => acc
case (x, _ ) if x <= 0 => acc
case (x, lh :: lt ) => f(x-lh,lt,acc ++ List(lh))
}
f(x,l,Nil)
}
}
Now you can use this like
List(1,2,3,4,5,6,7,8).takeSumLessThan(10)
Given a Scala sequence...
val sequence: Seq = List( 3, 1, 4, 1, 5, 9, 2, 6, 5 )
...say that I want to find all subsequences matching certain criteria, e.g. strings of odd numbers, and replace those with the result of some operation on that subsequence, say its length, producing a new sequence:
val sequence2: Seq = List( 2, 4, 3, 2, 6, 1 )
(Yes, this is a fairly contrived example, but it's concise.)
So far the best I've been able to do is this ugly imperative hack:
val sequence: Seq[Int] = List( 3, 1, 4, 1, 5, 9, 2, 6, 5 )
var sequence2 = List[Int]() // this is going to be our result
var subsequence = List[Int]()
for (s <- sequence) {
if (s % 2 == 0) {
if (!subsequence.isEmpty) {
sequence2 = sequence2 :+ subsequence.length
subsequence = List[Int]()
}
sequence2 = sequence2 :+ s
} else {
subsequence = subsequence :+ s
}
}
if (!subsequence.isEmpty) {
sequence2 = sequence2 :+ subsequence.length
}
Is there an elegant (/ functional) way to do this?
Using multiSpan for spanning a list into sublists by given criteria, consider this solution for the problem depicted above,
sequence.multiSpan( _ % 2 == 0 ).flatMap {
case h :: xs if h % 2 != 0 => List( (h::xs).length)
case h :: Nil => List(h)
case h :: xs => List(h, xs.length) }
Note that
sequence.multiSpan( _ % 2 == 0 )
List(List(3, 1), List(4, 1, 5, 9), List(2), List(6, 5))
and hence we flatMap these nested lists by considering three cases: whether the condition does not hold and so we apply a function; whether it is a singleton list (the condition holds); or else whether the first element holds and the rest needs be applied a function.
What you're looking for is a fold:
sequence.foldLeft(List(0)) { (soFar, next) =>
if(next % 2 == 0) soFar :+ next :+ 0 else soFar.init :+ (soFar.last + 1)
}.filter(_ != 0)
Or in a different style:
(List(0) /: sequence) {
case(soFar, next) if next % 2 == 0 => soFar :+ next :+ 0
case(soFar, _) => soFar.init :+ (soFar.last + 1)
}.filter(_ != 0)
Or with a foldRight instead, which is sometimes more performant:
(sequence :\ List(0)) {
case(next, soFar) if next % 2 == 0 => 0 :: next :: soFar
case(_, hd::tl) => (hd + 1)::tl
}.filter(_ != 0).reverse
You can read more about fold, foldLeft, foldRight, and other useful functions here and here.
I originally thought you were asking for all subsequences of a sequence. That might be useful in similar situations, so I'll leave this here. You can use inits and tails together to get all subsequences, and then use filter and map for your purposes:
val sequence = List( 3, 1, 4, 1, 5, 9, 2, 6, 5 )
val subsequences = sequence.tails.flatMap(_.inits).toList.distinct
subsequences.filter(_.forall(_ % 2 == 1)).map(_.length)
Here is my attempt at a recursive implementation
def subSequenceApply(list: List[Int], predicate: (Int)=> Boolean, func: (List[Int]) => Int):List[Int] = list match {
case Nil => Nil
case h :: t if !predicate(h) => h :: subSequenceApply(t, predicate, func)
case _ =>
val (matchSeq,nonMatch) = list.span(predicate)
func(matchSeq) :: subSequenceApply(nonMatch, predicate, func)
}
So given sequence in your example. You could run it as
subSequenceApply(sequence, _ % 2 != 0, _.length)