Parallel recursion in scala - scala

I am trying to parallelize recursive calls of sudoku solver from 25 lines Sudoku solver in Scala. I've changed their Fold into reduce
def reduce(f: (Int, Int) => Int, accu: Int, l: Int, u: Int): Int = {
accu + (l until u).toArray.reduce(f(accu, _) + f(accu, _))
}
which if run sequentially works fine, but when I change it into
accu + (l until u).toArray.par.reduce(f(accu, _) + f(accu, _))
the recursion reaches the bottom much more often and generates false solutions. I thought, that it will execute the bottom level recursion and work it's way up, but doesn't seem to do so.
I've also tried futures
def parForFut2(f: (Int, Int) => Int, accu: Int, l: Int, u: Int): Int = {
var sum: Int = accu
val vals = l until u
vals.foreach(t => scala.actors.Futures.future(sum + f(accu, t)))
sum
}
which appears to have the same problem as the par.reduce. I would appreciate any comment. The whole code is here:
object SudokuSolver extends App {
// The board is represented by an array of string
val source = scala.io.Source.fromFile("./puzzle")
val lines = (source.getLines).toArray
var m: Array[Array[Char]] = for (
str <- lines;
line: Array[Char] = str.toArray
) yield line
source.close()
// For printing m
def print = {
Console.println("");
refArrayOps(m) map (carr => Console.println(new String(carr)))
}
// The test for validity of n on position x,y
def invalid(i: Int, x: Int, y: Int, n: Char): Boolean =
i < 9 && (m(y)(i) == n || m(i)(x) == n ||
m(y / 3 * 3 + i / 3)(x / 3 * 3 + i % 3) == n || invalid(i + 1, x, y, n))
// Looping over a half-closed range of consecutive Integers [l..u)
// is factored out Into a higher-order function
def parReduce(f: (Int, Int) => Int, accu: Int, l: Int, u: Int): Int = {
accu + (l until u).toArray.par.reduce(f(accu, _) + f(accu, _))
}
// The search function examines each position on the board in turn,
// trying the numbers 1..9 in each unfilled position
// The function is itself a higher-order fold, accumulating the value
// accu by applying the given function f to it whenever a solution m
// is found
def search(x: Int, y: Int, f: (Int) => Int, accu: Int): Int = Pair(x, y) match {
case Pair(9, y) => search(0, y + 1, f, accu) // next row
case Pair(0, 9) => f(accu) // found a solution - print it and continue
case Pair(x, y) => if (m(y)(x) != '0') search(x + 1, y, f, accu) else
parForFut1((accu: Int, n: Int) =>
if (invalid(0, x, y, (n + 48).asInstanceOf[Char])) accu else {
m(y)(x) = (n + 48).asInstanceOf[Char];
val newaccu = search(x + 1, y, f, accu);
m(y)(x) = '0';
newaccu
}, accu, 1, 10)
}
// The main part of the program uses the search function to accumulate
// the total number of solutions
Console.println("\n" + search(0, 0, i => { print; i + 1 }, 0) + " solution(s)")
}

As far as I can tell, recursion is inherently sequential (i.e. not parallelizable).
I'd reason it like this: recursion means (put simply) 'call myself'. A function call always happens within one and exactly one thread.
If you are telling the function to call itself, then you are staying in that thread - you're not dividing the work (i.e. making it parallel).
Recursion and parallelism are related though, but not at the function-call level. They are related in the sense that tasks can be recursively decomposed into smaller parts, that can be performed in parallel.

After Andreas comment I changed the m: Array[Array[Char]] into m: List[List[Char]] which prevents any unnecessary and unwanted changes to it. The final looping method is
def reduc(f: (Int, Int) => Int,
accu: Int, l: Int, u: Int, m1: List[List[Char]]):Int =
accu + (l until u).toArray.par.reduce(f(accu, _) + f(accu, _))
and I had to pass m as an argument to each used function, so every one of them had its own instance of it. The whole code:
object SudokuSolver extends App{
// The board is represented by an Array of strings (Arrays of Chars),
val source = scala.io.Source.fromFile("./puzzle")
val lines = source.getLines.toList
val m: List[List[Char]] = for (
str <- lines;
line: List[Char] = str.toList
) yield line
source.close()
// For prInting m
def printSud(m: List[List[Char]]) = {
Console.println("")
m map (println)
}
Console.println("\nINPUT:")
printSud(m)
def invalid(i:Int, x:Int, y:Int, n:Char,m1: List[List[Char]]): Boolean =
i < 9 && (m1(y)(i) == n || m1(i)(x) == n ||
m1(y / 3 * 3 + i / 3)(x / 3 * 3 + i % 3) == n ||
invalid(i + 1, x, y, n, m1))
def reduc(f: (Int, Int) => Int, accu: Int, l: Int, u: Int,
m1: List[List[Char]]): Int =
accu + (l until u).toArray.par.reduce(f(accu, _) + f(accu, _))
def search(x: Int, y: Int, accu: Int, m1: List[List[Char]]): Int =
Pair(x, y) match {
case Pair(9, y) => search(0, y + 1, accu, m1) // next row
case Pair(0, 9) => { printSud(m1); accu + 1 } // found a solution
case Pair(x, y) =>
if (m1(y)(x) != '0')
search(x + 1, y, accu, m1) // place is filled, we skip it.
else // box is not filled, we try all n in {1,...,9}
reduc((accu: Int, n: Int) => {
if (invalid(0, x, y, (n + 48).asInstanceOf[Char], m1))
accu
else { // n fits here
val line = List(m1(y).patch(x, Seq((n + 48).asInstanceOf[Char]), 1))
val m2 = m1.patch(y, line, 1)
val newaccu = search(x + 1, y, accu, m2);
val m3 = m1.patch(y, m1(y).patch(x, Seq(0), 1), 1)
newaccu
}
}, accu, 1, 10, m1)
}
Console.println("\n" + search(0, 0, 0, m) + " solution(s)")
}

Related

Optimal way to find neighbors of element of collection in circular manner

I have a Vector and I'd like to find neighbors of given element.
Say if we have Vector(1, 2, 3, 4, 5) and then:
for element 2, result must be Some((1, 3))
for element 5, result must be Some((4, 1))
for element 1, result must be Some((5, 2))
for element 6, result must be None
and so on..
I have not found any solution in standard lib(please point me if there is one), so got the next one:
implicit class VectorOps[T](seq: Vector[T]) {
def findNeighbors(elem: T): Option[(T, T)] = {
val currentIdx = seq.indexOf(elem)
val firstIdx = 0
val lastIdx = seq.size - 1
seq match {
case _ if currentIdx == -1 || seq.size < 2 => None
case _ if seq.size == 2 => seq.find(_ != elem).map(elem => (elem, elem))
case _ if currentIdx == firstIdx => Some((seq(lastIdx), seq(currentIdx + 1)))
case _ if currentIdx == lastIdx => Some((seq(currentIdx - 1), seq(firstIdx)))
case _ => Some((seq(currentIdx - 1), seq(currentIdx + 1)))
}
}
}
The question is: how this can be simplified/optimized using stdlib?
def neighbours[T](v: Seq[T], x: T): Option[(T, T)] =
(v.last +: v :+ v.head)
.sliding(3, 1)
.find(_(1) == x)
.map(x => (x(0), x(2)))
This uses sliding to create a 3 element window in the data and uses find to match the middle value of the 3. Adding the last/first to the input deals with the wrap-around case.
This will fail if the Vector is too short so needs some error checking.
This version is safe for all input
def neighbours[T](v: Seq[T], x: T): Option[(T, T)] =
(v.takeRight(1) ++ v ++ v.take(1))
.sliding(3, 1)
.find(_(1) == x)
.map(x => (x(0), x(2)))
Optimal when number of calls with the same sequence is about or more than seq.toSet.size:
val elementToPair = seq.indicies.map(i => seq(i) ->
(seq((i - 1 + seq.length) % seq.length), seq((i + 1 + seq.length) % seq.length)
).toMap
elementToPair.get(elem)
// other calls
Optimal when number of calls with the same sequence less than seq.toSet.size:
Some(seq.indexOf(elem)).filterNot(_ == -1).map { i =>
(seq((i - 1 + seq.length) % seq.length), seq((i + 1 + seq.length) % seq.length) }

Product of Array Except Self with tail recursion

I would like to know if below function can be rewritten using tail recursion and using recursion in this case is any helpful in terms of time/space complexity?, below is what i have tried without tail recursion
input:[4,2,4,6]
output:[48,96,48,32]
def productExceptSelf(nums: Array[Int]): Array[Int]={
val len = nums.length
val output_arr= new Array[Int](len)
output_arr(0)=1
for(i<- 1 to len-1)
{
output_arr(i) = nums(i-1) * output_arr(i-1)
}
var R =1
var j=len-1
while(j>=0)
{
output_arr(j) = output_arr(j)* R
R = R * nums(j)
j-=1
}
output_arr
}
Solution without using division.
def productExceptSelf(nums: Array[Int]): Array[Int] =
Array.fill(nums.length)(nums)
.zipWithIndex
.map{case (ns,x) => ns.patch(x,Seq(),1).product}
Not sure how would you expect to write this using tail-recursion, but the simplest way would be something like this:
PS: I am using ArraySeq which is an immutable array (that was introduced on 2.13), feel free to keep using normal arrays.
def productExceptSelf(nums: ArraySeq[Int]): ArraySeq[Int] = {
val totalProduct = nums.product
nums.map(x => totalProduct / x)
}
Solution without using division.
def productExceptSelf(nums: ArraySew[Int]) : ArraySeq[Int] =
ArraySeq.tabulate(nums.length) { i =>
nums.foldLeft(1 -> 0) { case ((acc, j), x) =>
val newAcc = if (i == j) acc else acc * x
newAcc -> (j + 1)
}._1
}
Try this. It keeps track of the index and multiplies if the index of the current element isn't the same. However, it's not very idiomatic.
def productExceptSelf(nums: Array[Int]): Array[Int] =
productExceptSelf(nums, Array.fill(nums.size)(1), 0).toArray
def productExceptSelf(orig: Array[Int], res: Array[Int], i: Int): Array[Int] =
if (i == orig.size) res
else productExceptSelf(
orig,
res.zipWithIndex.map {
case (n, j) => if (j == i) n else n * orig(i)
},
i + 1
)
I like this one better:
def productExceptSelf(nums: Array[Int]): Array[Int] =
nums.indices.map {
i => nums.slice(0, i).product * nums.slice(i + 1, nums.size).product
}.toArray
You might prefer a view to do it lazily
def productExceptSelf(nums: Array[Int]) =
nums.indices.map {
i => nums.view.slice(0, i).product * nums.view.slice(i + 1, nums.size).product
}
# Starting from the right and recursing left, compute the right side product
# and pass it down. Upon reaching the left, compute the left side product,
# update the array, and bubble that value up.
def prod_not_self(arr, i, right):
if (i == 0):
left = 1
else:
left = arr[i-1] * prod_not_self(arr, i - 1, right * arr[i])
arr[i] = right * left
return left
if (__name__ == '__main__'):
arr = [1, 2, 3, 4]
print(arr)
prod_not_self(arr, len(arr) - 1, 1)
print(arr)
print()
arr = [-1, 1, 0, -3, 3]
print(arr)
prod_not_self(arr, len(arr) - 1, 1)
print(arr)

Define recursive lambda expression in scala

I am trying to define a recursive lambda expression in scala and struggling a bit with sintax, if think that this is just a syntax:
Here is what I have so far (not compilable):
type rec = (Int => Int, Int)
val f = (x : Int) => x + x
val y : rec = (f:Int => Int, x:Int) => if (x > 0) y( f, 1) else 1
Error I am getting:
ScalaFiddle.scala:14: error: ScalaFiddle.rec does not take parameters
val y : rec = (f:Int => Int, x:Int) => if (x > 0) y( f, 1) else 1
^
Original code sample I am trying to optimize (which works fine):
case class Rec[I, O](fn : (I => O, I) => O) extends (I => O) {
def apply(v : I) = fn(this, v)
}
val sum = Rec[Int, Int]((f, v) => if (v == 0) 0 else v + f(v - 1))
Any help would be appreciated.
Thanks
rec is a tuple of type Tuple2[Int => Int,Int].
in your statement val y : rec = (f:Int => Int, x:Int) => if (x > 0) y( f, 1) else 1, you are trying to call a apply function on the tuple y (y(f,1)). Since the tuple doesnt have a apply function defined you are getting the error rec does not take parameters
as per your sample code your type rec (Int => Int, Int) => Int.
so the code sample would be
type rec = (Int => Int, Int) => Int
val f = (x : Int) => x + x
val y : rec = (f:Int => Int, x:Int) => if (x > 0) y( f, 1) else 1
Check This link for this answer explanation
var sumIt:(Int => Int) = (x: Int) => {if(x<=1) 1 else sumIt(x-1)+x

Three Sum to N in Scala

Is there a better way than this example to find three numbers from a list that sum to zero in scala? Right now, I feel like my functional way may not be the most efficient and it contains duplicate tuples. What is the most efficient way to get rid of duplicate tuples in my current example?
def secondThreeSum(nums:List[Int], n:Int):List[(Int,Int,Int)] = {
val sums = nums.combinations(2).map(combo => combo(0) + combo(1) -> (combo(0), combo(1))).toList.toMap
nums.flatMap { num =>
val tmp = n - num
if(sums.contains(tmp) && sums(tmp)._1 != num && sums(tmp)._2 != num) Some((num, sums(tmp)._1, sums(tmp)._2)) else None
}
}
This is pretty simple, and doesn't repeat any tuples:
def f(nums: List[Int], n: Int): List[(Int, Int, Int)] = {
for {
(a, i) <- nums.zipWithIndex;
(b, j) <- nums.zipWithIndex.drop(i + 1)
c <- nums.drop(j + 1)
if n == a + b + c
} yield (a, b, c)
}
Use .combinations(3) to generate all distinct possible triplets of your start list, then keep only those that sum up to n :
scala> def secondThreeSum(nums:List[Int], n:Int):List[(Int,Int,Int)] = {
nums.combinations(3)
.collect { case List(a,b,c) if (a+b+c) == n => (a,b,c) }
.toList
}
secondThreeSum: (nums: List[Int], n: Int)List[(Int, Int, Int)]
scala> secondThreeSum(List(1,2,3,-5,2), 0)
res3: List[(Int, Int, Int)] = List((2,3,-5))
scala> secondThreeSum(List(1,2,3,-5,2), -1)
res4: List[(Int, Int, Int)] = List((1,3,-5), (2,2,-5))
Here is a solution that's O(n^2*log(n)). So it's quite a lot faster for large lists.
Also it uses lower level language features to increase the speed even further.
def f(nums: List[Int], n: Int): List[(Int, Int, Int)] = {
val result = scala.collection.mutable.ArrayBuffer.empty[(Int, Int, Int)]
val array = nums.toArray
val mapValueToMaxIndex = scala.collection.mutable.Map.empty[Int, Int]
nums.zipWithIndex.foreach {
case (n, i) => mapValueToMaxIndex += (n -> math.max(i, (mapValueToMaxIndex.getOrElse(n, i))))
}
val size = array.size
var i = 0
while(i < size) {
val a = array(i)
var j = i+1
while(j < size) {
val b = array(j)
val c = n - b - a
mapValueToMaxIndex.get(c).foreach { maxIndex =>
if(maxIndex > j) result += ((a, b, c))
}
j += 1
}
i += 1
}
result.toList
}

error: type mismatch; found : (Int, Int) => Int required: Int

I'm new to scala and confused why this code is giving me this error.
def div(m: Int, n: Int, i: Int): Int = {
(m: Int, n: Int) =>
if ((m - n) <= 0)
return i
else
div((m-n), n, (i+1))
}
Help appreciated.
It looks like you're returning a function rather than an Int like you're declaring.
Is this what you're trying to do:
def div(m: Int, n: Int, i: Int): Int = if ((m - n) <= 0) return i else div((m-n), n, (i+1))
(x: A) => y: B means an anonymous function of type A => B, so the expression you have between the braces is a function (Int, Int) => Int, and that's what gets returned.
You use a big number of superflous stuff, the return- keyword, parenthesis, and the whole (m: Int, n:Int) => - part.
def div (m: Int, n: Int, count: Int): Int =
if ((m - n) <= 0) count else div (m - n, n, count + 1)
If you like to use a match, you could do it this way:
def div (m: Int, n: Int, count: Int = 1): Int = (m - n) match {
case (diff: Int) if (diff <= 0) => count
case _ => div (m - n, n, count + 1) }
(note the default-argument of count = 1).
m,n,i are a little bit too much short-named variables for my taste. Beneath count, nominator, denominator would fit.
However, the implentation returns
(0 to 2).map (x => div (14+x, 5, 1))
res61: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 3, 4)
where I would expect (2, 3, 3) - you're rounding in the opposite direction.
if ((m - n) < 0) i-1 else ...
would fix that - changing the comparator, and returning i-1 (count-1).
However, this is not testet for values including 0 and negative values.