For one of my cases in algorithms I am required to create a model of a load balancer model for multiple processors. Lately I became interested in Scala so I decided that it would be great to create this program in Scala. I'm not really familiar with the concept of functional programming so any feedback will be welcome. Please note that I am not asking about the correctness of my algorithm as this is my homework.
object HelloWorld {
def randomElements(arg: Integer): Double = {
val r = scala.util.Random
return r.nextDouble()
}
// used for debugging
def return1Elements(arg: Integer): Double ={
return 1
}
def fillJobs(size: Integer, fillingFunction: (Integer) => Double): Array[Double] = {
val array = new Array[Double](size);
for (el <- 0 to size -1) {
array(el) = fillingFunction(el);
}
return array
}
def fillProcessors(size: Integer): Array[Double] = {
val array = new Array[Double](size);
for (el <- 0 to size -1) {
array(el) = 0
}
return array
}
def result(processors: Array[Double]): Double = {
return processors.max
}
def findMaxSolver(processorsArray: Array[Double], jobsArray: Array[Double]): Double = {
val sortedJobs = jobsArray.sortWith(_ > _)
var sortedProcessors = processorsArray
for(processorIndex <- 0 to processorsArray.size -1){
sortedProcessors(processorIndex) += sortedJobs(processorIndex)
}
for(job <- sortedJobs.slice(sortedProcessors.size, sortedJobs.size)){
sortedProcessors = sortedProcessors.sortWith(_<_)
sortedProcessors(0) += job
}
return result(sortedProcessors)
}
def solve(processorsArray: Array[Double], jobsArray: Array[Double],
solvingFunction: (Array[Double], Array[Double]) => Double): Double = {
val processors = processorsArray.clone()
val jobs = jobsArray.clone()
return solvingFunction(processors, jobs)
}
def main(args: Array[String]) {
val JOB_NUMBER = 1024
val PROCESSOR_NUMBER = 8
val jobs = fillJobs(JOB_NUMBER, randomElements)
val processors = fillProcessors(PROCESSOR_NUMBER)
println("Job times")
println("============================")
for (element <- jobs) {
println(element)
}
println("============================")
println("Results")
println("Find max solver " + solve(processors, jobs, findMaxSolver))
}
}
-
3\$\begingroup\$ As this is homework, do you mind telling us when you'll be turning it in? It's great that you want to make your code as good as possible, but some of us have an ethical issue with wantonly improving people's grades. \$\endgroup\$nhgrif– nhgrif2015年05月01日 22:49:18 +00:00Commented May 1, 2015 at 22:49
-
\$\begingroup\$ The date of turning in is 5.05.2015 \$\endgroup\$CucumisSativus– CucumisSativus2015年05月02日 08:04:23 +00:00Commented May 2, 2015 at 8:04
2 Answers 2
Below are some of the changes I would make to your code. In my opinion one of the nice aspects of Scala is that it gives you all sorts of ways to reduce the amount of work your mind has to do in order to decipher code. As an example, one of the first things I did was declare a type ArrD
that is equivalent to Array[Double]
. I then just substitued where necessary and the code (to my mind) became more readable. The choice of ArrD
was arbitrary on my part, you could if you wanted use ArrayDouble
instead. Along these lines I shortened all of you variable and value names.
As the program is set up right now you don't need to pass in a procs
array, but I left it in anyway. As you mentioned this is a homework assignment so I'll leave a bit of mystery as to why this is. And really you don't need the take
and the drop
.
Next note that jobs.sorted
is equivalent to jobs.sortWith(_ > _)
.
And finally (for now) checkout how I initialized jobs
and procs
. If you still would like to use your randomElements
function you should look into the method called tabulate
.
Cheers.
object O {
type ArrD = Array[Double]
def findMaxSolver(procs: ArrD, jobs: ArrD): Double = {
val sJobs = jobs.sorted
var sProcs = sJobs.take(procs.size)
for(job <- sJobs.drop(procs.size)){
sProcs = sProcs.sorted
sProcs(0) += job
}
sProcs.max
}
def solve(procs: ArrD, jobs: ArrD, f: (ArrD, ArrD) => Double) = f(procs, jobs)
def run = {
val jobNum = 1024
val procNum = 8
val jobs = Array.fill(jobNum)(scala.util.Random.nextDouble())
val procs = Array.fill(procNum)(0.0)
println(s"RESULTS:\nFind max solver ${solve(procs, jobs, findMaxSolver)}")
}
}
Avoid explicit return
statements when possible
As is typical in functional languages,
functions (and expression blocks) return the value of the last expression,
making explicit return
statements unnecessar. For example instead of this:
def fillJobs(size: Integer, fillingFunction: (Integer) => Double): Array[Double] = { val array = new Array[Double](size); for (el <- 0 to size -1) { array(el) = fillingFunction(el); } return array }
Write like this:
def fillJobs(size: Integer, fillingFunction: (Integer) => Double): Array[Double] = {
val array = new Array[Double](size);
for (el <- 0 to size -1) {
array(el) = fillingFunction(el);
}
array
}
Pass functions as parameters
Take full advantage that in a functional language you can pass functions as parameters.
For example, rewrite fillProcessors
in terms of fillJobs
:
def fillProcessors(size: Integer): Array[Double] =
fillJobs(size, _ => 0)
Use 0 until n
instead of 0 until n - 1
The use of 0 to n - 1
is so common that there exists another variant which is equivalent: 0 until n
.
So the loop in fillJobs
can use this:
for (el <- 0 until size) { ... }