Skip to content

Instantly share code, notes, and snippets.

@deyindra
Created March 12, 2017 05:24
Show Gist options
  • Save deyindra/3e76ecc7e8857614819cfd4f23de98a1 to your computer and use it in GitHub Desktop.
Save deyindra/3e76ecc7e8857614819cfd4f23de98a1 to your computer and use it in GitHub Desktop.
Custom Random Generator
package org.idey.scala.generator
import scala.util.Random
/**
* Generator Trait for any Random object generator if any types
* @tparam T type of any [[scala.Any]]
*/
trait Generator[+T] {
self =>
def generate : T
def map[S](f: T=>S): Generator[S] = new Generator[S] {
def generate:S = f(self.generate)
}
def flatMap[S](f: T=>Generator[S]): Generator[S] = new Generator[S] {
def generate:S = f(self.generate).generate
}
}
/**
* Random Integers generator return integer value based on [[Random]]
*/
object Integers extends Generator[Int]{
override def generate: Int = {
new Random().nextInt()
}
}
/**
* Random Boolean generator randomly generate either true or false base on [[Integers]] provide the integer is greater
* than 0
*
*/
object Booleans extends Generator[Boolean]{
override def generate: Boolean = {
(Integers map {x => x >0}).generate
}
}
/**
* Always return a +ve integer between low and high (low inclusive)
* @param lo lower boundary
* @param hi higher boundary
* @see [[Integers]]
*/
case class IntervalRandomInteger(lo : Int, hi : Int) extends Generator[Int] {
override def generate: Int = {
require(lo >=0 )
require(hi > lo )
(Integers map {x => if (x > 0 ) lo + x%(hi - lo) else lo + (-x)%(hi - lo)}).generate
}
}
/**
* Always return the same value
* @param x type of T
* @tparam T type of any [[scala.Any]]
*/
case class Singleton[T](x : T) extends Generator[T]{
override def generate: T = x
}
/**
* Return any single value randomly from the seq
* @param xs [[scala.Seq]] of type T
* @tparam T type of any [[scala.Any]]
*/
case class ChooseOneGenerator[T](xs:T*) extends Generator[T]{
override def generate: T = {
(IntervalRandomInteger(0, xs.length) map {x=>xs(x)}).generate
}
}
/**
* Return random [[scala.List]] of type T by selected values from xs
* @param xs [[scala.Seq]] of type T
* @tparam T type of any [[scala.Any]]
*/
case class RandomListGenerator[T](xs:T*) extends Generator[List[T]]{
override def generate: List[T] = {
def generateRandomList(acc:List[T]):List[T] = {
val isEmpty = Booleans.generate
if(isEmpty){
if(acc.isEmpty)
Nil
else
acc
}else{
(IntervalRandomInteger(0, xs.length) map {x=>xs(x)}).generate :: generateRandomList(acc)
}
}
generateRandomList(List())
}
}
trait Tree[+T]
case class Leaf[T] (t : T) extends Tree[T]
case class Inner[T](left : Tree[T], right: Tree[T]) extends Tree[T]
/**
* Return random [[Tree]] of type T by selected values from xs
* @param xs [[scala.Seq]] of type T
* @tparam T type of any [[scala.Any]]
*/
case class RandomTree[T] (xs:T*) extends Generator[Tree[T]]{
override def generate: Tree[T] = {
val isLeaf = Booleans.generate
val value : T = (IntervalRandomInteger(0, xs.length) map {x=>xs(x)}).generate
if(isLeaf)
Leaf(value)
else
Inner(generate,generate)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment