- How to generate transitive closure of set of tuples?
- //one transitive step
- def addTransitive[A, B](s: Set[(A, B)]) = {
- s ++ (for ((x1, y1) <- s; (x2, y2) <- s if y1 == x2) yield (x1, y2))
- }
- //repeat until we don't get a bigger set
- def transitiveClosure[A,B](s:Set[(A,B)]):Set[(A,B)] = {
- val t = addTransitive(s)
- if (t.size == s.size) s else transitiveClosure(t)
- }
- println(transitiveClosure(Set((1,2), (2,3), (3,4))))
- def unfoldRight[A, B](seed: B)(f: B => Option[(A, B)]): List[A] = f(seed) match {
- case Some((a, b)) => a :: unfoldRight(b)(f)
- case None => Nil
- }
- def unfoldLeft[A, B](seed: B)(f: B => Option[(B, A)]) = {
- def loop(seed: B)(ls: List[A]): List[A] = f(seed) match {
- case Some((b, a)) => loop(b)(a :: ls)
- case None => ls
- }
- loop(seed)(Nil)
- }
- def transitiveClosure(input: Set[(Int, Int)]) = {
- val map = input.toMap
- def closure(seed: Int) = unfoldLeft(map get seed) {
- case Some(`seed`) => None
- case Some(n) => Some(seed -> n -> (map get n))
- case _ => None
- }
- map.keySet flatMap closure
- }
- def closure(seed: Int) = unfoldRight(seed) {
- case n if map.get(n) != seed => map get n map (x => seed -> x -> x)
- case _ => None
- }
- def closure(seed: Int) = unfoldRight(map get seed) {
- case Some(`seed`) => Some(seed -> seed -> None)
- case Some(n) => Some(seed -> n -> (map get n))
- case _ => None
- }
- input.groupBy(_._1) mapValues ( _ map (_._2) )
- def transitiveClosure[T]( dag: Map[ T, List[T] ] ) = {
- var tc = Map.empty[ T, List[T] ]
- def getItemTC( item:T ): List[T] = tc.get(item) match {
- case None =>
- val itemTC = dag(item) flatMap ( x => x::getItemTC(x) )
- tc += ( item -> itemTC )
- itemTC
- case Some(itemTC) => itemTC
- }
- dag.keys foreach getItemTC
- tc
- }
- scala> val a = List((1,2), (2,3), (3,4))
- a: List[(Int, Int)] = List((1,2), (2,3), (3,4))
- scala> val (xx, yy) = a unzip
- xx: List[Int] = List(1, 2, 3)
- yy: List[Int] = List(2, 3, 4)
- scala> for(x <- xx; y <- yy if (x != y && x < y)) yield (x,y)
- res32: List[(Int, Int)] = List((1,2), (1,3), (1,4), (2,3), (2,4), (3,4))