I am solving a programming exercise that goes like this:
A file contains a list of equalities between positive integers sums, one for each line, each one terminated by a semicolon, without whitespaces. These equalities can either be right or be wrong. For example, consider the following file:
2+3+12=9+8; 2+3+4=9; 22=3+4+5+10; 3+5+1=4+44;
Write a program that takes the filename as its first argument and outputs the ratio of correct lines. For example, given the file above the program should output 0.75.
My solution in Scala is the following, and it works, but I am looking for a way to rewrite it without the var's.
import scala.io.Source
object Hello {
def main(args: Array[String]): Unit = {
var count: Int = 0
var correct: Int = 0
Source.fromFile(args(0)).getLines().zipWithIndex.foreach { case (line, i) =>
val regex = """^[1-9][0-9]*(\+[1-9][0-9]*)*=[1-9][0-9]*(\+[1-9][0-9]*)*;$""".r
regex findFirstIn line match {
case Some(_) =>
case None => throw new Exception("Error reading file, line " + i)
}
val sums = line.substring(0, line.length - 1).split('=').map {
_.split('+').map(Integer.parseInt).sum
}
count += 1
correct += (if (sums(0) == sums(1)) 1 else 0)
}
println("The ratio is " + correct.toFloat/count)
}
}
I tried to turn that foreach into a map, like so:
import scala.io.Source
object Hello {
def main(args: Array[String]): Unit = {
val file = Source.fromFile(args(0))
val correct = file.getLines().zipWithIndex.map({ case (line, i) =>
val regex = """^[1-9][0-9]*(\+[1-9][0-9]*)*=[1-9][0-9]*(\+[1-9][0-9]*)*;$""".r
regex findFirstIn line match {
case Some(_) =>
case None => throw new Exception("Error reading file, line " + i)
}
val sums = line.substring(0, line.length - 1).split('=').map {
_.split('+').map(Integer.parseInt).sum
}
return if (sums(0) == sums(1)) 1 else 0
}).sum
println("The ratio is " + correct/file.getLines().length)
}
}
The compiler complains:
Warning:(15, 38) a pure expression does nothing in statement position; you may be omitting necessary parentheses
return if (sums(0) == sums(1)) 1 else 0
^
Warning:(15, 45) a pure expression does nothing in statement position; you may be omitting necessary parentheses
return if (sums(0) == sums(1)) 1 else 0
^
Warning:(15, 7) enclosing method main has result type Unit: return value discarded
return if (sums(0) == sums(1)) 1 else 0
^
Error:(16, 8) ambiguous implicit values:
both object BigIntIsIntegral in object Numeric of type scala.math.Numeric.BigIntIsIntegral.type
and object ShortIsIntegral in object Numeric of type scala.math.Numeric.ShortIsIntegral.type
match expected type Numeric[B]
}).sum
^
Error:(16, 8) could not find implicit value for parameter num: Numeric[B]
}).sum
^
Error:(16, 8) not enough arguments for method sum: (implicit num: Numeric[B])B.
Unspecified value parameter num.
}).sum
^