From ec608257af69e4865de7d79c7c88e4ab7710407a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ali=20Sinan=20K=C3=B6ksal?= <alisinan@gmail.com>
Date: Tue, 8 Nov 2011 05:54:36 +0000
Subject: [PATCH] Random generation of red-black trees using ScalaCheck

---
 scalacheck-testcases/.RedBlackTree.scala.swp | Bin 0 -> 12288 bytes
 scalacheck-testcases/RedBlackTree.scala      | 115 +++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 scalacheck-testcases/.RedBlackTree.scala.swp
 create mode 100644 scalacheck-testcases/RedBlackTree.scala

diff --git a/scalacheck-testcases/.RedBlackTree.scala.swp b/scalacheck-testcases/.RedBlackTree.scala.swp
new file mode 100644
index 0000000000000000000000000000000000000000..2e890afaec248d96d8ac36518b0a45c8241f7317
GIT binary patch
literal 12288
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

literal 0
HcmV?d00001

diff --git a/scalacheck-testcases/RedBlackTree.scala b/scalacheck-testcases/RedBlackTree.scala
new file mode 100644
index 000000000..30bbb9222
--- /dev/null
+++ b/scalacheck-testcases/RedBlackTree.scala
@@ -0,0 +1,115 @@
+import org.scalacheck._
+import Gen._
+import Arbitrary.arbitrary
+
+object Specs {
+  sealed abstract class Color
+  case class Red() extends Color
+  case class Black() extends Color
+ 
+  sealed abstract class Tree
+  case class Empty() extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  sealed abstract class OptionInt
+  case class SomeInt(v : Int) extends OptionInt
+  case class NoneInt() extends OptionInt
+
+  def max(a: Int, b: Int) : Int = {
+    if (a >= b) a else b
+  } ensuring (res => res >= a && res >= b)
+
+  def size(t: Tree) : Int = (t match {
+    case Empty() => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }) ensuring (_ >= 0)
+
+  def height(t: Tree) : Int = (t match {
+    case Empty() => 0
+    case Node(_,l,_,r) => max(height(l), height(r)) + 1
+  }) ensuring (_ >= 0)
+
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(),_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(), l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red(), l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty() => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty() => 0
+    case Node(Black(), l, _, _) => blackHeight(l) + 1
+    case Node(Red(), l, _, _) => blackHeight(l)
+  }
+
+  def valuesWithin(t : Tree, bound : Int) : Boolean = t match {
+    case Empty() => true
+    case Node(_,l,v,r) => 0 <= v && v <= bound && valuesWithin(l,bound) && valuesWithin(r,bound)
+  }
+
+  def orderedKeys(t : Tree) : Boolean = orderedKeys(t, NoneInt(), NoneInt())
+
+  def orderedKeys(t : Tree, min : OptionInt, max : OptionInt) : Boolean = t match {
+    case Empty() => true
+    case Node(c,a,v,b) =>
+      val minOK = 
+        min match {
+          case SomeInt(minVal) =>
+            v > minVal
+          case NoneInt() => true
+        }
+      val maxOK =
+        max match {
+          case SomeInt(maxVal) =>
+            v < maxVal
+          case NoneInt() => true
+        }
+      minOK && maxOK && orderedKeys(a, min, SomeInt(v)) && orderedKeys(b, SomeInt(v), max)
+  }
+
+  def isRedBlackTree(t : Tree) : Boolean = {
+    blackBalanced(t) && redNodesHaveBlackChildren(t) && orderedKeys(t) // && isBlack(t)
+  }
+}
+object RedBlackTree {
+  import Specs._
+
+  val genLeaf = value(Empty())
+
+  def genColor: Gen[Color] = oneOf(Black(), Red())
+
+  val genNode = for {
+    v <- Gen.choose(1, 10)
+    left <- genTree
+    right <- genTree
+    color <- genColor
+  } yield Node(color, left, v, right)
+
+  def genTree: Gen[Tree] = oneOf(genLeaf, genNode)
+
+  def main(args: Array[String]): Unit = {
+    val iter = (new Iterator[Tree] {
+      private var counter = 0
+      def hasNext : Boolean = true || counter < 10
+      def next : Tree = { counter += 1; genTree.sample.get }
+    })
+
+    val s = scala.collection.mutable.Set[Int]()
+
+    for (t <- iter if isRedBlackTree(t)) {
+      //println("Here is a tree : " + t)
+      s += (size(t))
+      println(s)
+    }
+  }
+}
-- 
GitLab