Skip to content

Instantly share code, notes, and snippets.

@valtih1978
Last active July 27, 2017 10:59
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 valtih1978/9a7b104a616249128e76f676af75e2f2 to your computer and use it in GitHub Desktop.
Save valtih1978/9a7b104a616249128e76f676af75e2f2 to your computer and use it in GitHub Desktop.
scala solutions
// task and parallel definition can be found at https://www.coursera.org/learn/parprog1/discussions/weeks/1/threads/2gsI2DHVEeaKAhJC1hWxEQ/replies/-avxXTIBEeabvwrOSKMg4w/comments/O5yTH3K6EeeM7BK4-ybiDA
/** Computes the blurred RGBA value of a single pixel of the input image. */
def boxBlurKernel(src: Img, x: Int, y: Int, radius: Int): RGBA = {
val xMin = clamp(x-radius, 0, src.width-1)
val xMax = clamp(x+radius, 0, src.width-1)
val yMin = clamp(y-radius, 0, src.height-1)
val yMax = clamp(y+radius, 0, src.height-1)
var (i,j,n) = (xMin, yMin, 0.0)
var r,g,b,a = 0.0
while (i <= xMax) {
while (j <= yMax) {
val p = src(i,j)
r += red(p); g += green(p);
b += blue(p); a += alpha(p)
n += 1; j += 1
}; i += 1; j = yMin
}
rgba((r/n) toInt, (g/n) toInt, (b/n) toInt, (a/n) toInt)
}
object VerticalBoxBlur {
def blur(src: Img, dst: Img, from: Int, end: Int, radius: Int): Unit = {
for {
y <- 0 until src.height
x <- from until end // it is faster if x is inner. Speedup is like 1.8 vs 2.0
} dst(x,y) = boxBlurKernel(src, x,y,radius)
}
def parBlur(src: Img, dst: Img, numTasks: Int, radius: Int): Unit = {
val stripWidth = src.width / numTasks
val tasks = (0 until src.width by stripWidth) map (start =>
task(blur(src, dst, start, start + stripWidth, radius)))
tasks.map(_.join)
}
}
object HorizontalBoxBlur {
def blur(src: Img, dst: Img, from: Int, end: Int, radius: Int): Unit = {
for {
x <- 0 until src.width
y <- from until end // when y in internal loop, speedup is 2.18, when external, speedup = 1.7
} dst(x,y) = boxBlurKernel(src,x,y, radius)
}
def parBlur(src: Img, dst: Img, numTasks: Int, radius: Int): Unit = {
val stripHeight = src.height / numTasks
val tasks = (0 until src.height by stripHeight) map (startY =>
task(blur(src, dst, startY, (startY + stripHeight) min src.height, radius)))
tasks.foreach(_.join)
}
}
object count_change {
def countChange(money: Int, coins: List[Int]): Int = true match {
case _ if money == 0 => 1
case _ if money < 0 || coins.isEmpty => 0
case _ => countChange(money - coins.head, coins) + countChange(money, coins.tail)
}
countChange(5, List(2,3))
countChange(4, List(2,1))
type Threshold = (Int, List[Int]) => Boolean
/** In parallel, counts the number of ways change can be made from the
* specified list of coins for the specified amount of money.
*/
def parCountChange(money: Int, coins: List[Int], threshold: Threshold): Int = {
if (threshold(money, coins) || coins.isEmpty || money < 0) countChange(money, coins)
else {
val (c1, c2) = parallel(parCountChange(money - coins.head, coins, threshold),
parCountChange(money, coins.tail, threshold))
c1 + c2
}
}
/** Threshold heuristic based on the starting money. */
def moneyThreshold(startingMoney: Int): Threshold = (money, _) => money <= (2 * startingMoney) / 3
parCountChange(5, List(2,3), moneyThreshold(5))
parCountChange(4, List(2,1), moneyThreshold(4))
def totalCoinsThreshold(totalCoins: Int): Threshold =
(_, coins) => coins.size <= (2 * totalCoins) / 3
parCountChange(5, List(2,3), totalCoinsThreshold(2))
def combinedThreshold(startingMoney: Int, allCoins: List[Int]): Threshold = {
(money, coins) => money * coins.size <= (startingMoney * allCoins.size / 2)
}
}
// PART II
object par_balance {
def reduceLen(seq: Seq[Char]): Int = {
if (seq.length < 2) seq.length
else {
val (half1, half2) = seq.view.splitAt(seq.length/2)
//val (l,r) = (reduceLen(half1), reduceLen(half2)) // does not hang
// ASK!
// the following hangs during the test but not in worksheet
val (l,r) = parallel(reduceLen(half1), reduceLen(half2))
l + r
}
} //> reduceLen: (seq: Seq[Char])Int
//reduceLen("1234567890")
def balance(chars: Seq[Char]): Boolean = {
def aux(pos: Int, acc: Int): Boolean =
if (acc < 0) false
else if (pos == chars.length) acc == 0
else chars(pos) match {
case '(' => aux(pos+1, acc+1)
case ')' => aux(pos+1, acc-1)
case _ => aux(pos + 1, acc)
} ; aux(0, 0)
} //> balance: (chars: Seq[Char])Boolean
balance("") //> res0: Boolean = true
balance("123") //> res1: Boolean = true
balance("(df())") //> res2: Boolean = true
balance("())(") //> res3: Boolean = false
balance("(((") //> res4: Boolean = false
// https://stackoverflow.com/questions/12892701/abort-early-in-a-fold
def balance2(chars: Iterable[Char]): Boolean = {
val (bool, int) = chars.foldLeft(true -> 0){
case ((bool, int), char) => char match {
case '(' => bool -> (int + 1)
case ')' => (bool && int != 0) -> (int - 1)
case _ => bool -> int
}
}; bool && (int == 0)
} //> balance2: (chars: Iterable[Char])Boolean
balance2("") //> res5: Boolean = true
balance2("123") //> res6: Boolean = true
balance2("(df())") //> res7: Boolean = true
balance2("())(") //> res8: Boolean = false
balance2("(((") //> res9: Boolean = false
def balance22(chars: Iterable[Char]): Boolean = {
chars.foldLeft(0){
case (acc, char) => char match {
case '(' => acc + 1
case ')' => if (acc == 0) return false
acc - 1
case _ => acc
}
} == 0
} //> balance22: (chars: Iterable[Char])Boolean
balance22("") //> res10: Boolean = true
balance22("123") //> res11: Boolean = true
balance22("(df())") //> res12: Boolean = true
balance22("())(") //> res13: Boolean = false
balance22("(((") //> res14: Boolean = false
def balance3(chars: Iterable[Char]): Boolean = {
val code = Map('(' -> 1, ')' -> -1).withDefaultValue(0)
def loop(chLs: List[Char], acc: Int = 0): Int = chLs match {
case head::tail if acc >= 0 => loop(tail, acc + code(head))
case _ => acc
}
loop(chars.toList) == 0
} //> balance3: (chars: Iterable[Char])Boolean
balance3("") //> res15: Boolean = true
balance3("123") //> res16: Boolean = true
balance3("(df())") //> res17: Boolean = true
balance3("())(") //> res18: Boolean = false
balance3("(((") //> res19: Boolean = false
def mapChunk(s: Iterable[Char]) : (Int, Int) = {
s.foldLeft(0 -> 0){case ((credit, balance), char) => char match {
case '(' => credit -> (balance + 1)
case ')' => val b2 = balance - 1
credit.min(b2) -> b2 // credit marks minimal balance
case _ => credit -> balance
}}
} //> mapChunk: (s: Iterable[Char])(Int, Int)
def reduce2(strings: Iterable[Char]*): Boolean = {
(strings map (mapChunk) foldLeft (0)){
case (acc, (credit, balance)) =>
if (acc < -credit) return false
acc + balance
// ensure that balance never goes below zero for concatenated strings
} == 0
} //> reduce2: (strings: Iterable[Char]*)Boolean
mapChunk("") //> res20: (Int, Int) = (0,0)
mapChunk("123") //> res21: (Int, Int) = (0,0)
mapChunk(" ( ( ) ) ") //> res22: (Int, Int) = (0,0)
mapChunk(" () )( ") //> res23: (Int, Int) = (-1,0)
mapChunk("(((") //> res24: (Int, Int) = (0,3)
reduce2(" ( (", ") ) ") //> res25: Boolean = true
reduce2(" () )( ") //> res26: Boolean = false
reduce2("(((") //> res27: Boolean = false
// traverse maps a pair of (left open, totalBalance) into
// (left open, right open). This is needed to combine/concatinate
// chunks for reduction.
def traverse(chunk: Iterable[Char]) = {
val (left, totalBalance) = mapChunk(chunk)
//given )))()()( mapChunk produces -3,-2 and traverse maps this pair
// into 3, 1 since 1 is amount that we added to -3 to get -2.
//That is, -3+x=-2 => x = -2 - (-3)
(-left, totalBalance - left)
} //> traverse: (chunk: Iterable[Char])(Int, Int)
traverse("") //> res28: (Int, Int) = (0,0)
traverse("123") //> res29: (Int, Int) = (0,0)
traverse(" ( ( ) ) ") //> res30: (Int, Int) = (0,0)
traverse(" () )( ") //> res31: (Int, Int) = (1,1)
traverse("(((") //> res32: (Int, Int) = (0,3)
def combine(chunk1: (Int, Int), chunk2: (Int, Int)): (Int, Int) = {
// closed is amount of parenthesis closed in the middle when we attach
// chunk2 to chunk1
val closed = chunk1._2 min (chunk2._1)
(chunk1._1 + chunk2._1 - closed, chunk1._2 + chunk2._2 - closed)
} //> combine: (chunk1: (Int, Int), chunk2: (Int, Int))(Int, Int)
combine(traverse(""), traverse("123")) //> res33: (Int, Int) = (0,0)
combine(traverse(" ( ( ) ) "), traverse(" () )( "))
//> res34: (Int, Int) = (1,1)
// connecting ((( to ) should give 1,3 sincewe have 1 unclosed on left and 3 unclosed on right
combine(traverse(" ) "), traverse("((( ")) //> res35: (Int, Int) = (1,3)
combine(traverse(" () )( "), traverse("((( ")) //> res36: (Int, Int) = (1,4)
combine(traverse("((("), traverse(" () )( ")) //> res37: (Int, Int) = (0,3)
combine(traverse("((("), traverse(")))")) //> res38: (Int, Int) = (0,0)
def reduce3(seq: Seq[Char], th: Int): (Int, Int) = {
//println("reducing " + seq.mkString("") + ", " + (seq.length < 2))
if (seq.length < th) traverse(seq)
else {
val (half1, half2) = seq.view.splitAt(seq.length/2)
val (l,r) = parallel(reduce3(half1, th), reduce3(half2, th))
combine(l,r)
}
} //> reduce3: (seq: Seq[Char], th: Int)(Int, Int)
reduce3("", 3) //> res39: (Int, Int) = (0,0)
reduce3("))", 3) //> res40: (Int, Int) = (2,0)
reduce3("))(((", 3) //> res41: (Int, Int) = (2,3)
reduce3(")) () ( () ((", 3) //> res42: (Int, Int) = (2,3)
/** Returns `true` iff the parentheses in the input `chars` are balanced.
*/
def parBalance(chars: Seq[Char], threshold: Int): Boolean = {
reduce3(chars, threshold) == (0,0)
} //> parBalance: (chars: Seq[Char], threshold: Int)Boolean
parBalance("", 3) //> res43: Boolean = true
parBalance("))",3) //> res44: Boolean = false
parBalance("))(((", 3) //> res45: Boolean = false
parBalance(")) () ( () ((", 3) //> res46: Boolean = false
//> res47: Int(1) = 1
}
// PART III
object scan_tree {
trait Tree[T]
case class Leaf[T](value: T) extends Tree[T]
case class Node[T](l: Tree[T], r: Tree[T]) extends Tree[T]
def map[U,V](t: Tree[U])( f: U => V): Tree[V] = t match {
case Leaf(a) => Leaf(f(a))
case Node(l,r) => Node(map(l)(f), map(r)(f))
}
val t = Node(Node(Leaf(1), Leaf(2)), Leaf(3))
map(t)( (a: Int) => a * 2)
map(t)( (a: Int) => List(a))
def reduce[T](t: Tree[T])( f: (T,T) => T): T = t match {
case Leaf(a) => a
case Node(l,r) => f(reduce(l)(f), reduce(r)(f))
}
val f = (a: Int,b: Int) => a+b
reduce(t)(f)
reduce(map(t)( List(_)))(_ ++ _)
def scanLeft[T](in: Array[T], a0: T, out: Array[T])(f: (T,T) => T) {
out(0) = a0; for (i <- 0 until in.length) {
out(i+1) = f(in(i), out(i))
}
}
val out = Array(9, 2,2,2)
scanLeft(Array(1,2,3), 0, out)((_ + _))
out
//https://www.coursera.org/learn/parprog1/lecture/934xD/parallel-scan-prefix-sum-operation
abstract class TreeRes[T](val res: T)
case class LeafRes[T](override val res: T) extends TreeRes[T](res)
case class NodeRes[T](l: TreeRes[T], override val res: T, r: TreeRes[T]) extends TreeRes[T](res)
def reduceRes[T](t: Tree[T])(f: (T, T)=> T): TreeRes[T] = t match {
case Leaf(v) => LeafRes(v)
case Node(l,r) =>
val (lR, rR) = (reduceRes(l)(f), reduceRes(r)(f))
NodeRes(lR, f(lR.res, rR.res), rR)
}
reduceRes(Node(Node(Leaf(1), Leaf(3)), Node(Leaf(8), Leaf(50))))(_ + _)
}
object week2_array_sweep4 {
abstract class TreeRes[A] { def reduced: A }
case class LeafRes[A](from: Int, to: Int, reduced: A) extends TreeRes[A]
case class NodeRes[A](l: TreeRes[A], reduced: A, r: TreeRes[A]) extends TreeRes[A]
var threshold = 100
def upsweep[A](inp: Array[A], from: Int, to: Int)(f: (A,A) => A): TreeRes[A] = {
if (to-from < threshold) LeafRes(from, to, inp.view.slice(from, to).reduce(f))
else {val mid = (from + to) / 2
val (l,r) = parallel(upsweep(inp, from, mid)(f), upsweep(inp, mid, to)(f))
NodeRes(l,f(l.reduced, r.reduced), r)
}
}
val a = Array(1,3,8,50); threshold = 3
val t1 = upsweep(a, 0, a.length)(_ + _)
def downsweep[A](inp: Array[A], t: TreeRes[A], a0: A, out: Array[A])(f: (A,A) => A): Unit = t match {
case LeafRes(from, to, _) => var (i, a) = (from, a0)
while (i < to) {a = f(a, inp(i)); i += 1; out(i) = a}
case NodeRes(l,_,r) => parallel(downsweep(inp, l, a0, out)(f),
downsweep(inp, r, f(a0,l.reduced), out)(f))
}
val o = Array.fill(a.length+1){-1}
downsweep(a,t1,100,o)(_ + _)
o
(0 until o.length) foreach (o(_) = -1)
def scanLeft[A](inp: Array[A], a0: A, out: Array[A])(f: (A,A) => A) {
val t = upsweep(inp, 0, inp.length)(f)
out(0) = a0; downsweep(inp, t, a0, out)(f)
}
scanLeft(a, 100, o)(_ + _)
o
}
object lineOfSight {
// ASK! What is the logic behid the algorithm? I studied it by rote but do not understand it.
// ASK! why max function if we can simply a.max(b) when neccessary?
def max(a: Float, b: Float): Float = if (a > b) a else b
//> max: (a: Float, b: Float)Float
sealed abstract class Tree { def maxPrevious: Float }
case class Leaf(from: Int, until: Int, maxPrevious: Float) extends Tree
case class Node(left: Tree, right: Tree) extends Tree {
// ASK! if querying maxprev iterates the whole tree
val maxPrevious = max(left.maxPrevious, right.maxPrevious)
}
def upsweepSequential(inp: Array[Float], from: Int, to: Int) = {
(from until to) map (i => inp(i)/i) reduce (_ max _)
} //> upsweepSequential: (inp: Array[Float], from: Int, to: Int)Float
val a = Array[Float](0f, 1f, 8f, 9f) //> a : Array[Float] = Array(0.0, 1.0, 8.0, 9.0)
val res = upsweepSequential(a, 1, 4) //> res : Float = 4.0
assert(res == 4f)
def upsweep(inp: Array[Float], from: Int, end: Int, threshold: Int): Tree = {
// ASK! if view is ok in place of upSweepSequential
if (end - from < threshold)
//Leaf(from, end, inp.view.slice(from, end).reduce(max))
Leaf(from, end, upsweepSequential(inp, from, end))
else { val mid = (from + end)/2
val (l,r) = parallel(upsweep(inp, from, mid, threshold), upsweep(inp, mid, end, threshold))
Node(l,r)
}
} //> upsweep: (inp: Array[Float], from: Int, end: Int, threshold: Int)sequential
//| .Tree
val t1 = upsweep(a, 1, a.length, 3) //> t1 : sequential.Tree = Node(Leaf(1,2,1.0),Leaf(2,4,4.0))
def downsweepSequential(inp: Array[Float], out: Array[Float], a0: Float, from: Int, to: Int) {
var (a, i) = (a0, from)
while (i < to) {a = a max (inp(i)/i); out(i) = a ; i +=1}
} //> downsweepSequential: (inp: Array[Float], out: Array[Float], a0: Float, from
//| : Int, to: Int)Unit
val output = new Array[Float](4) //> output : Array[Float] = Array(0.0, 0.0, 0.0, 0.0)
downsweepSequential(Array[Float](0f, 1f, 8f, 9f), output, 0f, 1, 4)
output //> res0: Array[Float] = Array(0.0, 1.0, 4.0, 4.0)
assert(output.toList == List(0f, 1f, 4f, 4f))
def downsweep(inp: Array[Float], out: Array[Float], angle0: Float, tree: Tree): Unit = tree match {
case Leaf(from, to, _) => var (a, i) = (angle0, from)
//while (i < to) {a = a.max(inp(i)); i += 1; out(i) = a}
while (i < to) {a = a max (inp(i)/i); out(i) = a; i += 1}
case Node(l,r) => parallel(downsweep(inp, out, angle0, l),
downsweep(inp, out, angle0.max(l.maxPrevious), r))
}
downsweep(a, output, 0f, t1)
output
def parLineOfSight(inp: Array[Float], out: Array[Float], threshold: Int) {
val tree = upsweep(inp, 1, inp.length, threshold)
out(0) = 0; downsweep(inp, out, out(0), tree)
}
parLineOfSight(a, output, 3)
output
def lineOfSight(input: Array[Float], output: Array[Float]): Unit = {
output(0) = 0
(1 until input.length) foreach {case i =>
output(i) = output(i-1) max (input(i)/i)
}
}
output
}
def classify(points: GenSeq[Point], means: GenSeq[Point]): GenMap[Point, GenSeq[Point]] = {
points groupBy (findClosest(_, means))
}
def update(classified: GenMap[Point, GenSeq[Point]], oldMeans: GenSeq[Point]): GenSeq[Point] = {
oldMeans.map(oldMean => findAverage(oldMean, classified.getOrElse(oldMean, List())))
}
def converged(eta: Double)(oldMeans: GenSeq[Point], newMeans: GenSeq[Point]): Boolean = {
(oldMeans zip newMeans) forall {case (old, nju) => old.squareDistance(nju) < eta}
}
@tailrec
final def kMeans(points: GenSeq[Point], means: GenSeq[Point], eta: Double): GenSeq[Point] = {
val classified = classify(points, means)
val updated = update(classified, means)
if (converged(eta)(means, updated)) updated else kMeans(points, updated, eta)
}
/// package.scala
// based on https://github.com/dnc1994/FuncScala/blob/master/parprog1/barneshut/src/main/scala/barneshut/package.scala
case class Empty(centerX: Float, centerY: Float, size: Float) extends Quad {
def massX: Float = centerX
def massY: Float = centerY
def mass: Float = 0
def total: Int = 0
def insert(b: Body): Quad = Leaf(centerX, centerY, size, Seq(b))
}
case class Fork(nw: Quad, ne: Quad, sw: Quad, se: Quad
) extends Quad {
def sum[N](attribute: Quad => N)(implicit n: Numeric[N]) =
List(ne, nw, se, sw).map(attribute).sum // performance will suffer
val centerX: Float = sum(_.centerX) / 4
val centerY: Float = sum(_.centerY) / 4
val size: Float = nw.size * 2
val mass: Float = sum(_.mass)
val massX: Float = if (mass == 0) centerX else sum(child => child.massX * child.mass) / mass
val massY: Float = if (mass == 0) centerY else sum(child => child.massY * child.mass) / mass
val total: Int = sum(_.total)
def insert(b: Body): Fork = true match {
case _ if (b.y > centerY && b.x > centerX) => Fork(nw,ne,sw,se.insert(b))
case _ if (b.y > centerY) => Fork(nw,ne, sw.insert(b), se)
case _ if (b.x > centerX) => Fork(nw, ne.insert(b), sw, se)
case _ => Fork(nw.insert(b), ne, sw, se)
}
}
case class Leaf(centerX: Float, centerY: Float, size: Float, bodies: Seq[Body])
extends Quad {
def sum(attribute: Body => Float) = bodies.map(attribute).sum
val mass = sum(_.mass)
val massX = sum(body => body.mass * body.x) / mass
val massY: Float = sum(body => body.mass * body.y) / mass
val total: Int = bodies.length
def insert(b: Body): Quad = {
val newBodies = bodies :+ b
if (size < minimumSize)
Leaf(centerX, centerY, size, newBodies)
else {
val (l,r,u,d) = (centerX - size/4, centerX + size/4, centerY-size/4, centerY+size/4)
val nw = Empty(l,u,size/2)
val ne = Empty(r,u,size/2)
val sw = Empty(l,d,size/2)
val se = Empty(r,d,size/2)
val f1 = Fork(nw, ne, sw, se)
//newBodies.foldLeft(f1){_.insert(_)}
assert(total == 1, total + " bodies in the leaf whereas only 1 expected")
f1.insert(bodies(0)).insert(b)
}
}
}
// did myself
def traverse(quad: Quad): Unit = (quad: Quad) match {
case Empty(_, _, _) =>
// no force
case Leaf(_, _, _, bodies) =>
// add force contribution of each body by calling addForce
bodies.foreach(b => addForce(b.mass, b.x, b.y))
case f @ Fork(nw, ne, sw, se) =>
// see if node is far enough from the body,
// or recursion is needed
(f.size / distance(f.centerX, f.centerY, x, y) < theta) match {
case true => addForce(f.mass, f.massX, f.mass)
case false => List(nw,ne,sw,se).foreach (traverse)
}
}
def +=(b: Body): SectorMatrix = {
// implemented this looking at the test where (25,47) is mapped to (2,3)
val fx = (b.x - boundaries.minX) / boundaries.width * sectorPrecision
val fy = (b.y - boundaries.minY) / boundaries.height * sectorPrecision
def clip(coord: Float): Int = if (coord < 0) 0 else
if (coord > sectorPrecision-1) sectorPrecision-1 else coord.toInt
val List(ix,iy) = List(fx,fy) map clip
this.apply(ix,iy) += b
this
}
def apply(x: Int, y: Int) = matrix(y * sectorPrecision + x)
def combine(that: SectorMatrix): SectorMatrix = {
//matrix.zip(that.matrix).map {case (cb1, cb2) => cb1.combine(cb2)}
(0 until matrix.length) foreach (i => matrix(i) =
matrix(i).combine(that.matrix(i)))
this
}
// Simulator.scala
// implemented myself
def updateBoundaries(boundaries: Boundaries, body: Body): Boundaries = {
val br = new Boundaries()
br.minX = boundaries.minX.min(body.x)
br.maxX = boundaries.maxX.max(body.x)
br.minY = boundaries.minY.min(body.y)
br.maxY = boundaries.maxY.max(body.y)
br
}
// implemented myself
def mergeBoundaries(a: Boundaries, b: Boundaries): Boundaries = {
val br = new Boundaries()
br.minX = a.minX.min(b.minX)
br.minY = a.minY.min(b.minY)
br.maxX = a.maxX.max(b.maxX)
br.maxY = a.maxY.max(b.maxY)
br
}
def computeSectorMatrix(bodies: Seq[Body], boundaries: Boundaries): SectorMatrix = timeStats.timed("matrix") {
val parBodies = bodies.par
parBodies.tasksupport = taskSupport
// discovered myself
val z = new SectorMatrix(boundaries, SECTOR_PRECISION)
parBodies.aggregate(z)({case (z, b) => z.+=(b)}, _.combine(_))
}
def updateBodies(bodies: Seq[Body], quad: Quad): Seq[Body] = timeStats.timed("update") {
val parBodies = bodies.par
parBodies.tasksupport = taskSupport
//came up myself
parBodies.map(_.updated(quad)).seq
}
package quickcheck
import common._
import org.scalacheck._
import Arbitrary._
import Gen._
import Prop._
abstract class QuickCheckHeap extends Properties("Heap") with IntHeap {
// detects no bogus bugs
property("min1") = forAll { a: Int =>
val h = insert(a, empty)
findMin(h) == a
}
// detects bogus 2
property("min2") = forAll { (a: Int, b: Int) =>
val h = insert(a, empty)
val h2 = insert(b, h)
findMin(h2) == a.min(b)
}
// extend min2 to (dis)cover bogus3
property("min3") = forAll { (a: Int, b: Int) =>
val h = insert(a, empty)
val h2 = insert(b, h)
val h3 = deleteMin(h2)
val h4empty = deleteMin(h3)
findMin(h2) == a.min(b) && findMin(h3) == a.max(b) && isEmpty(h4empty)
}
// extend min3 to cover bogus4
// https://www.coursera.org/learn/progfun2/discussions/weeks/3/threads/GodSrudDEeapGAqfUypOxA
// Put at least 3 different integers in empty heap, and findMin will
// be the smallest one of those integers. If you deleteMin, findMin
// should return bigger value.
property("min4") = forAll { (a: Int, b: Int, c: Int) =>
val h = insert(a, empty)
val h2 = insert(b, h)
val h3 = insert(c, h2)
val h4 = deleteMin(h3)
val h5 = deleteMin(h4)
val h6empty = deleteMin(h5)
findMin(h3) == a.min(b).min(c) &&
findMin(h5) == a.max(b).max(c) && isEmpty(h6empty)
}
property("insert & delete") = forAll { a: Int =>
val h = insert(a, empty)
isEmpty(deleteMin(h))
}
lazy val genHeap: Gen[H] = oneOf(const(empty), for {
int <- arbitrary[Int]
heap <- genHeap
} yield insert(int, heap))
implicit lazy val arbHeap: Arbitrary[H] = Arbitrary(genHeap)
property("gen1") = forAll { (h: H) =>
val m = if (isEmpty(h)) 0 else findMin(h)
findMin(insert(m, h)) == m
}
// "meld" detects bogus1,2 and 5
property("meld") = forAll { (h1: H, h2: H) =>
isEmpty(h1) || isEmpty(h2) ||
{findMin(meld(h1, h2)) == findMin(h1).min(findMin(h2))}
}
property("sorted") = forAll { (h: H) =>
!isEmpty(h) ==> {
def aux(min: Int, h: H): Boolean =
if (isEmpty(h)) true else {
val f = findMin(h)
if (f < min) false else {
aux(f, deleteMin(h))
}
}
aux(findMin(h), deleteMin(h))
}
}
}
////////////////////// Tweets /////////////////////////////////
def tweetRemainingCharsCount(tweetText: Signal[String]): Signal[Int] = {
Signal{MaxTweetLength - tweetLength(tweetText())}
}
def colorForRemainingCharsCount(remainingCharsCount: Signal[Int]): Signal[String] = {
Signal(remainingCharsCount() match {
case i if i > 14 => "green"
case i if i > -1 => "orange"
case _ => "red"
})
}
////////////////////// Polynomial ////////////////////////////
object Polynomial {
def computeDelta(a: Signal[Double], b: Signal[Double],
c: Signal[Double]): Signal[Double] = {
Signal(b() * b() - 4 * a() * c())
}
def computeSolutions(a: Signal[Double], b: Signal[Double],
c: Signal[Double], delta: Signal[Double]): Signal[Set[Double]] = {
Signal {
val doubleA = 2 * a()
delta() match {
case d if d < 0 => Set()
case d if d == 0 => Set(-b() / doubleA)
case d => Set(math.sqrt(d), -math.sqrt(d)) map (_ + b()) map (_ / doubleA)
}
}
}
}
/////////////////////// Calculator //////////////////////////////
object Calculator {
def computeValues(
namedExpressions: Map[String, Signal[Expr]]): Map[String, Signal[Double]] = {
namedExpressions map {case (name, exprSig) => name -> Signal(eval(exprSig(), namedExpressions))}
}
def eval(expr: Expr, references: Map[String, Signal[Expr]]): Double = expr match {
case Literal(v) => v
case Plus(a: Expr, b: Expr) => eval(a, references) + eval(b, references)
case Minus(a: Expr, b: Expr) => eval(a, references) - eval(b, references)
case Times(a: Expr, b: Expr) => eval(a, references) * eval(b, references)
case Divide(a: Expr, b: Expr) => eval(a, references) / eval(b, references)
case Ref(name) => eval(references(name)(), references)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment