How to generate the power set of a set in Scala - scala

I have a Set of items of some type and want to generate its power set.
I searched the web and couldn't find any Scala code that adresses this specific task.
This is what I came up with. It allows you to restrict the cardinality of the sets produced by the length parameter.
def power[T](set: Set[T], length: Int) = {
var res = Set[Set[T]]()
res ++= set.map(Set(_))
for (i <- 1 until length)
res = res.map(x => set.map(x + _)).flatten
res
}
This will not include the empty set. To accomplish this you would have to change the last line of the method simply to res + Set()
Any suggestions how this can be accomplished in a more functional style?

Looks like no-one knew about it back in July, but there's a built-in method: subsets.
scala> Set(1,2,3).subsets foreach println
Set()
Set(1)
Set(2)
Set(3)
Set(1, 2)
Set(1, 3)
Set(2, 3)
Set(1, 2, 3)

Notice that if you have a set S and another set T where T = S ∪ {x} (i.e. T is S with one element added) then the powerset of T - P(T) - can be expressed in terms of P(S) and x as follows:
P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }
That is, you can define the powerset recursively (notice how this gives you the size of the powerset for free - i.e. adding 1-element doubles the size of the powerset). So, you can do this tail-recursively in scala as follows:
scala> def power[A](t: Set[A]): Set[Set[A]] = {
| #annotation.tailrec
| def pwr(t: Set[A], ps: Set[Set[A]]): Set[Set[A]] =
| if (t.isEmpty) ps
| else pwr(t.tail, ps ++ (ps map (_ + t.head)))
|
| pwr(t, Set(Set.empty[A])) //Powerset of ∅ is {∅}
| }
power: [A](t: Set[A])Set[Set[A]]
Then:
scala> power(Set(1, 2, 3))
res2: Set[Set[Int]] = Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3), Set(1, 2))
It actually looks much nicer doing the same with a List (i.e. a recursive ADT):
scala> def power[A](s: List[A]): List[List[A]] = {
| #annotation.tailrec
| def pwr(s: List[A], acc: List[List[A]]): List[List[A]] = s match {
| case Nil => acc
| case a :: as => pwr(as, acc ::: (acc map (a :: _)))
| }
| pwr(s, Nil :: Nil)
| }
power: [A](s: List[A])List[List[A]]

Here's one of the more interesting ways to write it:
import scalaz._, Scalaz._
def powerSet[A](xs: List[A]) = xs filterM (_ => true :: false :: Nil)
Which works as expected:
scala> powerSet(List(1, 2, 3)) foreach println
List(1, 2, 3)
List(1, 2)
List(1, 3)
List(1)
List(2, 3)
List(2)
List(3)
List()
See for example this discussion thread for an explanation of how it works.
(And as debilski notes in the comments, ListW also pimps powerset onto List, but that's no fun.)

Use the built-in combinations function:
val xs = Seq(1,2,3)
(0 to xs.size) flatMap xs.combinations
// Vector(List(), List(1), List(2), List(3), List(1, 2), List(1, 3), List(2, 3),
// List(1, 2, 3))
Note, I cheated and used a Seq, because for reasons unknown, combinations is defined on SeqLike. So with a set, you need to convert to/from a Seq:
val xs = Set(1,2,3)
(0 to xs.size).flatMap(xs.toSeq.combinations).map(_.toSet).toSet
//Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3),
//Set(1, 2))

Can be as simple as:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] =
xs.foldLeft(Seq(Seq[A]())) {(sets, set) => sets ++ sets.map(_ :+ set)}
Recursive implementation:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] = {
def go(xsRemaining: Seq[A], sets: Seq[Seq[A]]): Seq[Seq[A]] = xsRemaining match {
case Nil => sets
case y :: ys => go(ys, sets ++ sets.map(_ :+ y))
}
go(xs, Seq[Seq[A]](Seq[A]()))
}

All the other answers seemed a bit complicated, here is a simple function:
def powerSet (l:List[_]) : List[List[Any]] =
l match {
case Nil => List(List())
case x::xs =>
var a = powerSet(xs)
a.map(n => n:::List(x)):::a
}
so
powerSet(List('a','b','c'))
will produce the following result
res0: List[List[Any]] = List(List(c, b, a), List(b, a), List(c, a), List(a), List(c, b), List(b), List(c), List())

Here's another (lazy) version... since we're collecting ways of computing the power set, I thought I'd add it:
def powerset[A](s: Seq[A]) =
Iterator.range(0, 1 << s.length).map(i =>
Iterator.range(0, s.length).withFilter(j =>
(i >> j) % 2 == 1
).map(s)
)

Here's a simple, recursive solution using a helper function:
def concatElemToList[A](a: A, list: List[A]): List[Any] = (a,list) match {
case (x, Nil) => List(List(x))
case (x, ((h:List[_]) :: t)) => (x :: h) :: concatElemToList(x, t)
case (x, (h::t)) => List(x, h) :: concatElemToList(x, t)
}
def powerSetRec[A] (a: List[A]): List[Any] = a match {
case Nil => List()
case (h::t) => powerSetRec(t) ++ concatElemToList(h, powerSetRec (t))
}
so the call of
powerSetRec(List("a", "b", "c"))
will give the result
List(List(c), List(b, c), List(b), List(a, c), List(a, b, c), List(a, b), List(a))

Related

Grouping a list

I want to group elements of a list such as :
val lst = List(1,2,3,4,5)
On transformation it should return a new list as:
val newlst = List(List(1), List(1,2), List(1,2,3), List(1,2,3,4), Lis(1,2,3,4,5))
You can do it this way:
lst.inits.toList.reverse.tail
(1 to lst.size map lst.take).toList should do it.
Not as pretty or short as others, but gotta have some tail recursion for the soul:
def createFromElements(list: List[Int]): List[List[Int]] = {
#tailrec
def createFromElements(l: List[Int], p: List[List[Int]]): List[List[Int]] =
l match {
case x :: xs =>
createFromElements(xs, (p.headOption.getOrElse(List()) ++ List(x)) :: p)
case Nil => p.reverse
}
createFromElements(list, Nil)
}
And now:
scala> createFromElements(List(1,2,3,4,5))
res10: List[List[Int]] = List(List(1), List(1, 2), List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5))
Doing a foldLeft seems to be more efficient, though ugly:
(lst.foldLeft((List[List[Int]](), List[Int]()))((x,y) => {
val z = x._2 :+ y;
(x._1 :+ z, z)
}))._1

Best way to implement "zipLongest" in Scala

I need to implement a "zipLongest" function in Scala; that is, combine two sequences together as pairs, and if one is longer than the other, use a default value. (Unlike the standard zip method, which will just truncate to the shortest sequence.)
I've implemented it directly as follows:
def zipLongest[T](xs: Seq[T], ys: Seq[T], default: T): Seq[(T, T)] = (xs, ys) match {
case (Seq(), Seq()) => Seq()
case (Seq(), y +: rest) => (default, y) +: zipLongest(Seq(), rest, default)
case (x +: rest, Seq()) => (x, default) +: zipLongest(rest, Seq(), default)
case (x +: restX, y +: restY) => (x, y) +: zipLongest(restX, restY, default)
}
Is there a better way to do it?
Use zipAll :
scala> val l1 = List(1,2,3)
l1: List[Int] = List(1, 2, 3)
scala> val l2 = List("a","b")
l2: List[String] = List(a, b)
scala> l1.zipAll(l2,0,".")
res0: List[(Int, String)] = List((1,a), (2,b), (3,.))
If you want to use the same default value for the first and second seq :
scala> def zipLongest[T](xs:Seq[T], ys:Seq[T], default:T) = xs.zipAll(ys, default, default)
zipLongest: [T](xs: Seq[T], ys: Seq[T], default: T)Seq[(T, T)]
scala> val l3 = List(4,5,6,7)
l3: List[Int] = List(4, 5, 6, 7)
scala> zipLongest(l1,l3,0)
res1: Seq[(Int, Int)] = List((1,4), (2,5), (3,6), (0,7))
You can do this as a oneliner:
xs.padTo(ys.length, x).zip(ys.padTo(xs.length, y))

Inserting at position in List

This insert function is taken from :
http://aperiodic.net/phil/scala/s-99/p21.scala
def insertAt[A](e: A, n: Int, ls: List[A]): List[A] = ls.splitAt(n) match {
case (pre, post) => pre ::: e :: post
}
I want to insert an element at every second element of a List so I use :
val sl = List("1", "2", "3", "4", "5") //> sl : List[String] = List(1, 2, 3, 4, 5)
insertAt("'a", 2, insertAt("'a", 4, sl)) //> res0: List[String] = List(1, 2, 'a, 3, 4, 'a, 5)
This is a very basic implementation, I want to use one of the functional constructs. I think I need
to use a foldLeft ?
Group the list into Lists of size 2, then combine those into lists separated by the separation character:
val sl = List("1","2","3","4","5") //> sl : List[String] = List(1, 2, 3, 4, 5)
val grouped = sl grouped(2) toList //> grouped : List[List[String]] = List(List(1, 2), List(3, 4), List(5))
val separatedList = grouped flatMap (_ :+ "a") //> separatedList : <error> = List(1, 2, a, 3, 4, a, 5, a)
Edit
Just saw that my solution has a trailing token that isn't in the question. To get rid of that do a length check:
val separatedList2 = grouped flatMap (l => if(l.length == 2) l :+ "a" else l)
//> separatedList2 : <error> = List(1, 2, a, 3, 4, a, 5)
You could also use sliding:
val sl = List("1", "2", "3", "4", "5")
def insertEvery(n:Int, el:String, sl:List[String]) =
sl.sliding(2, 2).foldRight(List.empty[String])( (xs, acc) => if(xs.length == n)xs:::el::acc else xs:::acc)
insertEvery(2,"x",sl) // res1: List[String] = List(1, 2, x, 3, 4, x, 5)
Forget about insertAt, use pure foldLeft:
def insertAtEvery[A](e: A, n: Int, ls: List[A]): List[A] =
ls.foldLeft[(Int, List[A])]((0, List.empty)) {
case ((pos, result), elem) =>
((pos + 1) % n, if (pos == n - 1) e :: elem :: result else elem :: result)
}._2.reverse
Recursion and pattern matching are functional constructs. Insert the new elem by pattern matching on the output of splitAt then recurse with the remaining input. Seems easier to read but I'm not satisfied with the type signature for this one.
def insertEvery(xs: List[Any], n: Int, elem: String):List[Any] = xs.splitAt(n) match {
case (xs, List()) => if(xs.size >= n) xs ++ elem else xs
case (xs, ys) => xs ++ elem ++ insertEvery(ys, n, elem)
}
Sample runs.
scala> val xs = List("1","2","3","4","5")
xs: List[String] = List(1, 2, 3, 4, 5)
scala> insertEvery(xs, 1, "a")
res1: List[Any] = List(1, a, 2, a, 3, a, 4, a, 5, a)
scala> insertEvery(xs, 2, "a")
res2: List[Any] = List(1, 2, a, 3, 4, a, 5)
scala> insertEvery(xs, 3, "a")
res3: List[Any] = List(1, 2, 3, a, 4, 5)
An implementation using recursion:
Note n must smaller than the size of List, or else an Exception would be raised.
scala> def insertAt[A](e: A, n: Int, ls: List[A]): List[A] = n match {
| case 0 => e :: ls
| case _ => ls.head :: insertAt(e, n-1, ls.tail)
| }
insertAt: [A](e: A, n: Int, ls: List[A])List[A]
scala> insertAt("'a", 2, List("1", "2", "3", "4"))
res0: List[String] = List(1, 2, 'a, 3, 4)
Consider indexing list positions with zipWithIndex, and so
sl.zipWithIndex.flatMap { case(v,i) => if (i % 2 == 0) List(v) else List(v,"a") }

my combinations function returns an empty list

I am working on S-99: Ninety-Nine Scala Problems and already stuck at question 26.
Generate the combinations of K distinct objects chosen from the N elements of a list.
After wasting a couple hours, I decided to peek at a solution written in Haskell:
combinations :: Int -> [a] -> [[a]]
combinations 0 _ = [ [] ]
combinations n xs = [ y:ys | y:xs' <- tails xs
, ys <- combinations (n-1) xs']
It looks pretty straightforward so I decided to translate into Scala. (I know that's cheating.) Here's what I got so far:
def combinations[T](n: Int, ls: List[T]): List[List[T]] = (n, ls) match {
case (0, _) => List[List[T]]()
case (n, xs) => {
for {
y :: xss <- allTails(xs).reverse
ys <- combinations((n - 1), xss)
} yield y :: ys
}
}
My helper function:
def allTails[T](ls: List[T]): List[List[T]] = {
ls./:(0, List[List[T]]())((acc, c) => {
(acc._1 + 1, ls.drop(acc._1) :: acc._2)
})._2 }
allTails(List(0, 1, 2, 3)).reverse
//> res1: List[List[Int]] = List(List(0, 1, 2, 3), List(1, 2, 3), List(2, 3), List(3))
However, my combinations returns an empty list. Any idea?
Other solutions with explanation are very welcome as well. Thanks
Edit: The description of the question
Generate the combinations of K distinct objects chosen from the N elements of a list.
In how many ways can a committee of 3 be chosen from a group of 12 people? We all know that there are C(12,3) = 220 possibilities (C(N,K) denotes the well-known binomial coefficient). For pure mathematicians, this result may be great. But we want to really generate all the possibilities.
Example:
scala> combinations(3, List('a, 'b, 'c, 'd, 'e, 'f))
res0: List[List[Symbol]] = List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), ...
As Noah pointed out, my problem is for of an empty list doesn't yield. However, the hacky work around that Noah suggested is wrong. It adds an empty list to the result of every recursion step. Anyway, here is my final solution. I changed the base case to "case (1, xs)". (n matches 1)
def combinations[T](n: Int, ls: List[T]): List[List[T]] = (n, ls) match {
case (1, xs) => xs.map(List(_))
case (n, xs) => {
val tails = allTails(xs).reverse
for {
y :: xss <- allTails(xs).reverse
ys <- combinations((n - 1), xss)
} yield y :: ys
}
}
//combinations(3, List(1, 2, 3, 4))
//List(List(1, 2, 3), List(1, 2, 4), List(1, 3, 4), List(2, 3, 4))
//combinations(2, List(0, 1, 2, 3))
//List(List(0, 1), List(0, 2), List(0, 3), List(1, 2), List(1, 3), List(2, 3))
def allTails[T](ls: List[T]): List[List[T]] = {
ls./:(0, List[List[T]]())((acc, c) => {
(acc._1 + 1, ls.drop(acc._1) :: acc._2)
})._2
}
//allTails(List(0,1,2,3))
//List(List(3), List(2, 3), List(1, 2, 3), List(0, 1, 2, 3))
You made a mistake when translating the Haskell version here:
case (0, _) => List[List[T]]()
This returns an empty list. Whereas the Haskell version
combinations 0 _ = [ [] ]
returns a list with a single element, and that element is an empty list.
This is essentially saying that there is one way to choose zero items, and that is important because the code builds on this case recursively for the cases where we choose more items. If there were no ways to select zero items, then there would also be no ways to select one item and so on. That's what's happening in your code.
If you fix the Scala version to do the same as the Haskell version:
case (0, _) => List(List[T]())
it works as expected.
Your problem is using the for comprehension with lists. If the for detects an empty list, then it short circuits and returns an empty list instead of 'cons'ing your head element. Here's an example:
scala> for { xs <- List() } yield println("It worked!") // This never prints
res0: List[Unit] = List()
So, a kind of hacky work around for your combinations function would be:
def combinations[T](n: Int, ls: List[T]): List[List[T]] = (n, ls) match {
case (0, _) => List[List[T]]()
case (n, xs) => {
val tails = allTails(xs).reverse
println(tails)
for {
y :: xss <- tails
ys <- Nil :: combinations((n - 1), xss) //Now we're sure to keep evaulating even with an empty list
} yield y :: ys
}
}
scala> combinations(2, List(1, 2, 3))
List(List(1, 2, 3), List(2, 3), List(3))
List(List(2, 3), List(3))
List(List(3))
List()
res5: List[List[Int]] = List(List(1), List(1, 2), List(1, 3), List(2), List(2, 3), List(3))
One more way of solving it.
def combinations[T](n: Int, ls: List[T]): List[List[T]] = {
var ms: List[List[T]] = List[List[T]]();
val len = ls.size
if (n > len)
throw new Error();
else if (n == len)
List(ls)
else if (n == 1)
ls map (a => List(a))
else {
for (i <- n to len) {
val take: List[T] = ls take i;
val temp = combinations(n - 1, take.init) map (a => take.last :: a)
ms = ms ::: temp
}
ms
}
}
So combinations(2, List(1, 2, 3)) gives: List[List[Int]] = List(List(2, 1), List(3, 1), List(3, 2))

Does Scala have a statement equivalent to ML's "as" construct?

In ML, one can assign names for each element of a matched pattern:
fun findPair n nil = NONE
| findPair n (head as (n1, _))::rest =
if n = n1 then (SOME head) else (findPair n rest)
In this code, I defined an alias for the first pair of the list and matched the contents of the pair. Is there an equivalent construct in Scala?
You can do variable binding with the # symbol, e.g.:
scala> val wholeList # List(x, _*) = List(1,2,3)
wholeList: List[Int] = List(1, 2, 3)
x: Int = 1
I'm sure you'll get a more complete answer later as I'm not sure how to write it recursively like your example, but maybe this variation would work for you:
scala> val pairs = List((1, "a"), (2, "b"), (3, "c"))
pairs: List[(Int, String)] = List((1,a), (2,b), (3,c))
scala> val n = 2
n: Int = 2
scala> pairs find {e => e._1 == n}
res0: Option[(Int, String)] = Some((2,b))
OK, next attempt at direct translation. How about this?
scala> def findPair[A, B](n: A, p: List[Tuple2[A, B]]): Option[Tuple2[A, B]] = p match {
| case Nil => None
| case head::rest if head._1 == n => Some(head)
| case _::rest => findPair(n, rest)
| }
findPair: [A, B](n: A, p: List[(A, B)])Option[(A, B)]