Last active
July 27, 2017 10:59
-
-
Save valtih1978/9a7b104a616249128e76f676af75e2f2 to your computer and use it in GitHub Desktop.
scala solutions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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 | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////// 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