diff --git a/reductions/src/main/scala/reductions/LineOfSight.scala b/reductions/src/main/scala/reductions/LineOfSight.scala index fa57939..49cb5dc 100644 --- a/reductions/src/main/scala/reductions/LineOfSight.scala +++ b/reductions/src/main/scala/reductions/LineOfSight.scala @@ -41,13 +41,29 @@ case class Leaf(from: Int, until: Int, maxPrevious: Float) extends Tree object LineOfSight extends LineOfSightInterface { def lineOfSight(input: Array[Float], output: Array[Float]): Unit = { - ??? + var i = 1 + var max: Float = 0 + + output(0) = 0 + while (i < input.length) { + max = Math.max(max, input(i) / i) + output(i) = max + i += 1 + } } /** Traverses the specified part of the array and returns the maximum angle. */ def upsweepSequential(input: Array[Float], from: Int, until: Int): Float = { - ??? + var i = from + var max: Float = 0 + + while (i < until) { + max = Math.max(max, input(i) / i) + i += 1 + } + + max } /** Traverses the part of the array starting at `from` and until `end`, and @@ -60,7 +76,17 @@ object LineOfSight extends LineOfSightInterface { */ def upsweep(input: Array[Float], from: Int, end: Int, threshold: Int): Tree = { - ??? + if (end - from <= threshold) { + Leaf(from, end, upsweepSequential(input, from, end)) + } else { + val mid: Int = (end - from) / 2 + val (l, r) = parallel( + upsweep(input, from, from + mid, threshold), + upsweep(input, from + mid, end, threshold), + ) + + Node(l, r) + } } /** Traverses the part of the `input` array starting at `from` and until @@ -69,7 +95,14 @@ object LineOfSight extends LineOfSightInterface { */ def downsweepSequential(input: Array[Float], output: Array[Float], startingAngle: Float, from: Int, until: Int): Unit = { - ??? + var i = from + var max = startingAngle + + while (i < until) { + max = Math.max(max, input(i) / i) + output(i) = max + i += i + } } /** Pushes the maximum angle in the prefix of the array to each leaf of the @@ -77,13 +110,19 @@ object LineOfSight extends LineOfSightInterface { * the `output` angles. */ def downsweep(input: Array[Float], output: Array[Float], startingAngle: Float, - tree: Tree): Unit = { - ??? + tree: Tree): Unit = tree match { + case Leaf(from, until, _) => downsweepSequential(input, output, startingAngle, from, until) + case Node(l, r) => parallel( + downsweep(input, output, startingAngle, l), + downsweep(input, output, Math.max(startingAngle, l.maxPrevious), r), + ) } /** Compute the line-of-sight in parallel. */ def parLineOfSight(input: Array[Float], output: Array[Float], threshold: Int): Unit = { - ??? + val t = upsweep(input, 1, input.length, threshold) + downsweep(input, output, 0, t) + output(0) = 0 } } diff --git a/reductions/src/main/scala/reductions/ParallelCountChange.scala b/reductions/src/main/scala/reductions/ParallelCountChange.scala index 4c749c7..067e6a8 100644 --- a/reductions/src/main/scala/reductions/ParallelCountChange.scala +++ b/reductions/src/main/scala/reductions/ParallelCountChange.scala @@ -50,8 +50,16 @@ object ParallelCountChange extends ParallelCountChangeInterface { /** Returns the number of ways change can be made from the specified list of * coins for the specified amount of money. */ - def countChange(money: Int, coins: List[Int]): Int = { - ??? + def countChange(money: Int, coins: List[Int]): Int = money match { + case 0 => 1 + case _ => coins match { + case Nil => 0 + case c::cs => + if (money < c) 0 + else { + countChange(money - c, coins) + countChange(money, cs) + } + } } type Threshold = (Int, List[Int]) => Boolean @@ -60,20 +68,29 @@ object ParallelCountChange extends ParallelCountChangeInterface { * specified list of coins for the specified amount of money. */ def parCountChange(money: Int, coins: List[Int], threshold: Threshold): Int = { - ??? + if (threshold(money, coins) || money < 0 || coins == Nil) { + countChange(money, coins) + } else { + val (countLeft, countRight) = parallel( + parCountChange(money - coins.head, coins, threshold), + parCountChange(money, coins.tail, threshold) + ) + + countLeft + countRight + } } /** Threshold heuristic based on the starting money. */ def moneyThreshold(startingMoney: Int): Threshold = - ??? + (money, _) => money <= 2 * startingMoney / 3 /** Threshold heuristic based on the total number of initial coins. */ def totalCoinsThreshold(totalCoins: Int): Threshold = - ??? + (_, coins) => coins.length <= 2 * totalCoins / 3 /** Threshold heuristic based on the starting money and the initial list of coins. */ def combinedThreshold(startingMoney: Int, allCoins: List[Int]): Threshold = { - ??? + (money, coins) => money * coins.length <= startingMoney * allCoins.length / 2 } } diff --git a/reductions/src/main/scala/reductions/ParallelParenthesesBalancing.scala b/reductions/src/main/scala/reductions/ParallelParenthesesBalancing.scala index 21c1757..a54851f 100644 --- a/reductions/src/main/scala/reductions/ParallelParenthesesBalancing.scala +++ b/reductions/src/main/scala/reductions/ParallelParenthesesBalancing.scala @@ -40,22 +40,45 @@ object ParallelParenthesesBalancing extends ParallelParenthesesBalancingInterfac /** Returns `true` iff the parentheses in the input `chars` are balanced. */ def balance(chars: Array[Char]): Boolean = { - ??? + val z: (Int, Boolean) = (0, true) + val (s, alwaysAboveZero) = chars.foldLeft(z)({ case ((s, alwaysAboveZero), c) => c match { + case '(' => (s + 1, alwaysAboveZero) + case ')' => (s - 1, if (s - 1 < 0) false else alwaysAboveZero) + case _ => (s, alwaysAboveZero) + }}) + + alwaysAboveZero && s == 0 } /** Returns `true` iff the parentheses in the input `chars` are balanced. */ def parBalance(chars: Array[Char], threshold: Int): Boolean = { - def traverse(idx: Int, until: Int, arg1: Int, arg2: Int) /*: ???*/ = { - ??? + @tailrec + def traverse(idx: Int, until: Int, arg1: Int, arg2: Int): (Int, Int) = { + if (idx == until) (arg1, arg2) + else chars(idx) match { + case '(' => traverse(idx + 1, until, arg1 + 1, arg2) + case ')' => traverse(idx + 1, until, arg1 - 1, Math.min(arg1 - 1, arg2)) + case _ => traverse(idx + 1, until, arg1, arg2) + } } - def reduce(from: Int, until: Int) /*: ???*/ = { - ??? + def reduce(from: Int, until: Int): (Int, Int) = { + if (until - from <= threshold) { + traverse(from, until, 0, 0) + } else { + val mid: Int = (until - from) / 2 + val ((c1, min1), (c2, min2)) = parallel( + reduce(from, from + mid), + reduce(from + mid, until) + ) + + (c1 + c2, Math.min(min1, c1 + min2)) + } } - reduce(0, chars.length) == ??? + reduce(0, chars.length) == (0, 0) } // For those who want more: