I’m very new to Scala! However, I have the following working solution to Euler Problem 4 that I would like to use par on, just to see if I can do it:
import scala.math
object Problem4 {
def isPalindrome(x: Int): Boolean = {
val string = x.toString
string.reverseIterator.sameElements(string.iterator)
}
def getPairs(minimum: Int, maximum: Int) = {
for (i <- minimum to maximum view;
j <- minimum to maximum view)
yield (i, j)
}
def getAnswer(numberOfDigits: Int): Int = {
val maximum = math.pow(10, numberOfDigits).toInt
val minimum = math.pow(10, numberOfDigits - 1).toInt
val products = for {
pair <- getPairs(minimum, maximum)
product = pair match { case (i, j) => i * j }
if isPalindrome(product)
} yield product
products.par.max
}
def main(args: Array[String]) {
val answer = getAnswer(4)
println("Problem 4 answer: %s".format(answer))
}
} // object Problem4
Project Euler 4 asks for 3-digit numbers, and I’ve noticed that finding the answer for 4-digit numbers takes 63 seconds on my PC and only uses one processor on my dual-core system. This is despite applying par to the end of the for expression.
How do I parallelise this using par? Ideally I’d like finding the answer for 4 digits to take 30-40 seconds. Thanks!
EDIT: I’m pretty sure getPairs returns a View:
scala> def getPairs(minimum: Int, maximum: Int) = {
| for (i <- minimum to maximum view;
| j <- minimum to maximum view)
| yield (i, j)
| }
getPairs: (minimum: Int, maximum: Int)scala.collection.SeqView[(Int, Int),Seq[_]]
Moreover, adding par to the getPairs call returns a warning, still only uses one of my processors, and results in a java.lang.OutOfMemoryError: Java heap space exception:
[info] Loading project definition from M:\programming\testdriveneuler\src\problem4\project
[info] Set current project to euler (in build file:/M:/programming/testdriveneuler/src/problem4/)
[info] Compiling 1 Scala source to M:\programming\testdriveneuler\src\problem4\target\scala-2.9.2\classes...
[warn] M:\programming\testdriveneuler\src\problem4\src\main\scala\Problem4.scala:39: `withFilter' method does not yet exist on scala.collection.parallel.ParSeq[((Int, Int), Int)], using `filter' method instead
[warn] pair <- getPairs(minimum, maximum).par
[warn] ^
[warn] one warning found
EDIT: I’m explicitly interested in calculating the answer to Euler problem 4 for the product of 2 4-digit numbers. For reference the answer is 99000099.
So much complexity. It can be done with 2 functions
Update
(min to max).viewreturnsSeqView, which represents lazy version of collection.(min to max).view.parreturnsParSeq, parallel collection. In other words, callingparon lazy sequence will force it to evaluate. So, in this case you ought to choose between laziness and parallelism. It is hard to say what conversions are performed when you are moving fromSeqViewtoParSeqbut this unnecessary complexity is causingOutOfMemoryError.Update2
Yes,
foris just a syntactic sugar over higher order operations on collections. Desugared version offorloop will be something like: