Skip to content

Instantly share code, notes, and snippets.

@aspiwack
Created September 22, 2015 15:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aspiwack/ed53675d5a58ac1bf115 to your computer and use it in GitHub Desktop.
Save aspiwack/ed53675d5a58ac1bf115 to your computer and use it in GitHub Desktop.
Simple, naïve, generic diff implementation
package util
import scala.reflect.ClassTag
sealed abstract class Diffed[+A]
final case class Unchanged[+A](x: A) extends Diffed[A] {
override def toString: String = "Unchanged(" + x + ")"
}
final case class Changed[+A](x: A) extends Diffed[A] {
override def toString: String = "Changed(" + x + ")"
}
object StringDiff extends App {
def maxVector[A](v1: Vector[A], v2: Vector[A]): Vector[A] =
if (v1.length > v2.length) v1
else v2
// returns the longest common subsequence between [l1] and [l2]
def longestSubsequence[A: ClassTag](l1: Array[A], l2: Array[A]): Array[A] = {
// initialize matrix for dynamic algorithm
val n1 = l1.length
val n2 = l2.length
val lsubs: Array[Array[Vector[A]]] = Array.ofDim[Vector[A]](n1 + 1, n2 + 1)
// initialize matrix border
lsubs(0)(0) = Vector()
for (i <- 0 until n1) lsubs(i + 1)(0) = Vector()
for (j <- 0 until n2) lsubs(0)(j + 1) = Vector()
// fill matrix
for (
i <- 0 until n1;
j <- 0 until n2
) {
if (l1(i) == l2(j)) {
lsubs(i + 1)(j + 1) = lsubs(i)(j) :+ l1(i)
} else {
lsubs(i + 1)(j + 1) = maxVector(lsubs(i)(j + 1), lsubs(i + 1)(j))
}
}
// build return value
lsubs(n1)(n2) toArray
}
// [common] is a subsequence of [l], assumed to be the longest common
// subsequence with some other array
def diffOf[A: ClassTag](common: Array[A], l: Array[A]): Array[Diffed[A]] = {
var cursor = 0
l map ((x: A) => if (cursor < common.length && x == common(cursor)) { cursor += 1; Unchanged(x) } else Changed(x))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment