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