Related
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.
I tried to copy a Scala array using the yield keyword, but I got an vector in the end. Why and how can I get an copied array using yield?
scala> val s=Array(1,2,3,4,5); val copied_s=for (i<-0 until s.size) yield s(i)
The console returns
s: Array[Int] = Array(1, 2, 3, 4, 5)
copied_s: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5)
Use clone instead:
val c = s.clone
0 until ... creates a Range, and this is the source, from which the Vector is considered a good fit, not the Array.
scala> 0 until 4
res4: scala.collection.immutable.Range = Range(0, 1, 2, 3)
A big (...) helps too:
(for (i<-0 until s.size) yield s(i)).toArray
but clone is much smaller.
I am trying to generalize repeated, nested flatMap but not sure if one exists.
The following code will produce all combinations of n choose 3, :
def choose3flatMap(n: Int, r: Int = 3) =
(0 to n - r)
.flatMap(i => (i + 1 to n - (r - 1))
.flatMap(j => (j + 1 to n - (r - 2))
.map(k => Seq(i, j, k))))
Repeating the flatMap operation, we can get all combinations of n choose 5, :
def choose5flatMap(n: Int, r: Int = 5) =
(0 to n - r)
.flatMap(i => (i + 1 to n - (r - 1))
.flatMap(j => (j + 1 to n - (r - 2))
.flatMap(k => (k + 1 to n - (r - 3))
.flatMap(l => (l + 1 to n - (r - 4))
.map(m => Seq(i, j, k, l, m)))))
Clearly there is a pattern here. I would like to utilize this similarity to get a general solution for n choose r, . Is there a simple way to accomplish this. Perhaps a higher order function of some sort?
What I have tried:
Scala lets me rewrite the map/flatMap with a for expression. This reads cleaner, but the number of choices in still hard-coded.
def choose3Loop(n: Int, r: Int = 3) =
for {
i <- 0 to n - r
j <- i + 1 to n - (r - 1)
k <- j + 1 to n - (r - 2)
} yield Seq(i, j, k)
I can write a recursive solution directly using flatMap or utilizing the sugar of a for expression:
def combinationsRecursive(n: Int, r: Int, i: Int = 0): Seq[Seq[Int]] =
if (r == 1) (i until n).map(Seq(_))
else {
(i to n - r).flatMap(
i => combinationsRecursive(n, r - 1, i + 1).map(j => i +: j))
}
def combinationsRecursiveLoop(n: Int, r: Int, i: Int = 0): Seq[Seq[Int]] =
if (r == 1) (i until n).map(Seq(_))
else
for {
i <- i to n - r
j <- combinationsRecursiveLoop(n, r - 1, i + 1)
} yield i +: j
While these are solutions to the general problem, I wonder if there is a higher-level abstraction I am missing here that may be applicable to other problems as well. I recognize that for this particular application, I could do (0 to n).combinations(r) to use a library-provided implementation of computing combinations.
While the above code is Scala, in this case I am interested the functional programming aspect of it and not the language capabilities. If there is a solution but one that is not supported by Scala I am interested in that.
Edit: He is a sample caller and the resulting output by request:
scala> combinationsRecursiveLoop(5, 3)
res0: Seq[Seq[Int]] = Vector(List(0, 1, 2), List(0, 1, 3), List(0, 1, 4), List(0, 2, 3), List(0, 2, 4), List(0, 3, 4), List(1, 2, 3), List(1, 2, 4), List(1, 3, 4), List(2, 3, 4))
scala> combinationsRecursiveLoop(5, 3).map("("+_.mkString(", ")+")").mkString(" ")
res1: String = (0, 1, 2) (0, 1, 3) (0, 1, 4) (0, 2, 3) (0, 2, 4) (0, 3, 4) (1, 2, 3) (1, 2, 4) (1, 3, 4) (2, 3, 4)
It just provides all r-element subsets of the set of integers starting at zero containing n elements. More information on combinations can be found on Wikipedia.
Here is one way to look at this, that I have come up with.
You can extract one stage in your chain as a function f: List[Int] => List[List[Int]], that takes a List with a beginning of a combination, and prepends all possible next elements to it.
For example in choose(5, 3), f(List(2, 0)) would result in List(List(3, 2, 0), List(4, 2, 0)).
Here is a possible implementation of such a function with some processing for the initial case added:
val f: List[Int] => List[List[Int]] = l =>
(l.headOption.map(_ + 1).getOrElse(0) to n - (r - l.size))
.map(_ :: l).toList
Now, such a function is a Kleisli arrow Kleisli[List, List[Int], List[Int]], and it's endomorphic (has the same argument and return types).
There is a monoid instance for endomorphic kleisli arrows, where the monoid "addition" means the flatMap operation (or in pseudocode, f1 |+| f2 == a => f1(a).flatMap(f2)). So to replace your chain of flatMaps you need to "add" r instances of this f function, or in other words to multiply the f function by r.
This idea translates directly into Scalaz code:
import scalaz._, Scalaz._
def choose(n: Int, r: Int) = {
val f: List[Int] => List[List[Int]] = l =>
(l.headOption.map(_ + 1).getOrElse(0) to n - (r - l.size))
.map(_ :: l).toList
Endomorphic.endoKleisli(f).multiply(r).run(Nil)
}
And here is an example running it:
scala> choose(4, 3)
res1: List[List[Int]] = List(List(2, 1, 0), List(3, 1, 0), List(3, 2, 0), List(3, 2, 1))
The combinations are reversed, but it should be possible to make a version, that produces combinations with elements in the increasing order (or just run choose(n, r).map(_.reverse)).
Another improvement would be to make a lazy version, that returns Stream[List[Int]] (or even better a scalaz.EphemeralStream[List[Int]]: you don't want to have all the combinations cached in memory), but this is left as an exercise to the reader.
This question already has answers here:
What is the fastest way to write Fibonacci function in Scala?
(8 answers)
Closed 5 years ago.
def fibSeq(n: Int): List[Int] = {
var ret = scala.collection.mutable.ListBuffer[Int](1, 2)
while (ret(ret.length - 1) < n) {
val temp = ret(ret.length - 1) + ret(ret.length - 2)
if (temp >= n) {
return ret.toList
}
ret += temp
}
ret.toList
}
So the above is my code to generate a Fibonacci sequence using Scala to a value n. I am wondering if there is a more elegant way to do this in Scala?
This is a bit more elegant:
val fibs: Stream[Int] = 0 #:: fibs.scanLeft(1)(_ + _)
With Streams you "take" a number of values, which you can then turn into a List:
scala> fibs take 10 toList
res42: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
Update: I've written a blog post which goes more detail regarding how this solution works, and why you end up with a Fibonacci sequence!
There are many ways to define the Fibonacci sequence, but my favorite is this one:
val fibs:Stream[Int] = 0 #:: 1 #:: (fibs zip fibs.tail).map{ t => t._1 + t._2 }
This creates a stream that is evaluated lazily when you want a specific Fibonacci number.
EDIT:
First, as Luigi Plinge pointed out, the "lazy" at the beginning was unnecessary.
Second, go look at his answer, he pretty much did the same thing only more elegantly.
Not as elegant as Streams, not lazy, but tailrecursive and handles BigInt (which is easy to do with Luigis scanLeft too, but not so with Tal's zip - maybe just for me).
#tailrec
def fib (cnt: Int, low: BigInt=0, high: BigInt=1, sofar: List[BigInt]=Nil): List[BigInt] = {
if (cnt == 0) (low :: sofar).reverse else fib (cnt - 1, high, low + high, low :: sofar) }
scala> fib (75)
res135: List[BigInt] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853, 72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264, 806515533049393, 1304969544928657, 2111485077978050)
My favorite version is:
def fibs(a: Int = 0, b: Int = 1): Stream[Int] = Stream.cons(a, fibs(b, a+b))
With the default values you can just call fibs() and get the infinite Stream.
I also think it's highly readable despite being a one liner.
If you just want the first n then you can use take like fibs() take n, and if you need it as a list fibs() take n toList.
Here's yet another approach again using *Stream*s on an intermediary tuples:
scala> val fibs = Stream.iterate( (0,1) ) { case (a,b)=>(b,a+b) }.map(_._1)
fibs: scala.collection.immutable.Stream[Int] = Stream(0, ?)
scala> fibs take 10 toList
res68: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
I find this implementation to be more legible:
def fibonacci: Stream[Int] = {
def loop(a: Int, b: Int): Stream[Int] = (a + b) #:: loop(b, b + a)
loop(0, 1)
}
def fib:Stream[Int] ={
def go(f0: Int, f1:Int): Stream[Int] = {
Stream.cons(f0,go(f1,f0+f1))
}
go(0,1)
}
How do you replace an element by index with an immutable List.
E.g.
val list = 1 :: 2 ::3 :: 4 :: List()
list.replace(2, 5)
If you want to replace index 2, then
list.updated(2,5) // Gives 1 :: 2 :: 5 :: 4 :: Nil
If you want to find every place where there's a 2 and put a 5 in instead,
list.map { case 2 => 5; case x => x } // 1 :: 5 :: 3 :: 4 :: Nil
In both cases, you're not really "replacing", you're returning a new list that has a different element(s) at that (those) position(s).
In addition to what has been said before, you can use patch function that replaces sub-sequences of a sequence:
scala> val list = List(1, 2, 3, 4)
list: List[Int] = List(1, 2, 3, 4)
scala> list.patch(2, Seq(5), 1) // replaces one element of the initial sequence
res0: List[Int] = List(1, 2, 5, 4)
scala> list.patch(2, Seq(5), 2) // replaces two elements of the initial sequence
res1: List[Int] = List(1, 2, 5)
scala> list.patch(2, Seq(5), 0) // adds a new element
res2: List[Int] = List(1, 2, 5, 3, 4)
You can use list.updated(2,5) (which is a method on Seq).
It's probably better to use a scala.collection.immutable.Vector for this purpose, becuase updates on Vector take (I think) constant time.
You can use map to generate a new list , like this :
# list
res20: List[Int] = List(1, 2, 3, 4, 4, 5, 4)
# list.map(e => if(e==4) 0 else e)
res21: List[Int] = List(1, 2, 3, 0, 0, 5, 0)
It can also be achieved using patch function as
scala> var l = List(11,20,24,31,35)
l: List[Int] = List(11, 20, 24, 31, 35)
scala> l.patch(2,List(27),1)
res35: List[Int] = List(11, 20, 27, 31, 35)
where 2 is the position where we are looking to add the value, List(27) is the value we are adding to the list and 1 is the number of elements to be replaced from the original list.
If you do a lot of such replacements, it is better to use a muttable class or Array.
following is a simple example of String replacement in scala List, you can do similar for other types of data
scala> val original: List[String] = List("a","b")
original: List[String] = List(a, b)
scala> val replace = original.map(x => if(x.equals("a")) "c" else x)
replace: List[String] = List(c, b)