Skip to content

Instantly share code, notes, and snippets.

@pathikrit
Last active February 14, 2016 18:18
Show Gist options
  • Save pathikrit/7f19bda54bf071df5d07 to your computer and use it in GitHub Desktop.
Save pathikrit/7f19bda54bf071df5d07 to your computer and use it in GitHub Desktop.
Infer ordering given sorted collection
class OrderLearner[A](root: A) {
import scala.collection.mutable.{Map => Dict}
private val next = Dict.empty[A, Set[A]] withDefaultValue Set.empty[A]
def learn(words: Seq[A]*) = for {
i <- words.indices
_ = words(i).foreach(u => next(root) += u)
j <- words.indices drop (i+1)
(u, v) <- words(i) zip words(j) find {case (a, b) => a != b}
} next(u) += v
def inferOrdering(): Ordering[A] = {
val depth = Dict.empty[A, Int] withDefaultValue 0
def topologicalSort(visited: Set[A])(u: A): Unit = {
require(!visited(u), s"Cycle detected involving $u")
next(u).filterNot(visited).foreach(topologicalSort(visited + u))
depth(u) = depth(u) max visited.size
}
topologicalSort(Set.empty)(root)
Ordering.by(depth)
}
def nodes() = next.values.flatten.toSet
}
object AlphabetLearner extends OrderLearner('*') with App {
learn("alpha", "baby", "beta", "brownies", "cat", "dad", "dog", "elephant", "ralph", "orange")
val (alphabets, ordering) = (nodes(), inferOrdering())
for {
u <- alphabets
v <- alphabets if u != v
c = ordering.compare(u, v)
} println(if(c < 0) s"$u < $v" else if (c > 0) s"$v < $u" else s"$u $v: ambiguous")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment