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 .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.