1

我正在解决一个这样的编程练习:

一个文件包含一个正整数和之间的等式列表,每行一个,每行一个以分号结尾,没有空格。这些平等可能是对的,也可能是错的。例如,考虑以下文件:

2+3+12=9+8;
2+3+4=9;
22=3+4+5+10;
3+5+1=4+44;

编写一个程序,将文件名作为第一个参数并输出正确行数的比率。例如,给定上面的文件,程序应该输出 0.75。

我在 Scala 中的解决方案如下,它可以工作,但我正在寻找一种没有 var 的方法来重写它。

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)
  }
}

我试图把那个 foreach 变成一张地图,像这样:

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)
  }
}

编译器抱怨:

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
       ^
4

1 回答 1

5

您可以定义两个案例类来简化您的任务:

case class Equation(left:Sum,right:Sum) {
  // to check if both sides of equation are equal
  def isCorrect = left.sum == right.sum
}
object Equation {
  // a pattern to extract left and right part of the equation
  val equationPattern = "([0-9\\+]+)=([0-9\\+]+);".r
  // apply method for building equation from string
  def apply(line:String) = line match {
    // building new equation, but use Sum for left/right side parsing
    case equationPattern(left,right) => new Equation(Sum(left), Sum(right))
    case _ => throw new IllegalArgumentException("cannot parse equation")
  }
}

Equation类用于解析和分析您的方程式,但它使用嵌套案例类Sum来解析方程式的左侧或右侧部分。

case class Sum(elements:List[Int]) {
  // just sum all elements in this equation side
  def sum:Int = elements.sum
}
object Sum {
  // construct Sum from a String like "1+2+3+4"
  def apply(line:String) = new Sum(line.split("\\+").map(_.toInt).toList)
}

使用这些简单的案例类,我们可以轻松解析和分析像您这样的方程:

object Main {
  def main(args: Array[String]): Unit = {
    println(Equation("1+2=3+4;").isCorrect) // prints 'false'
    println(Equation("1+2+4=3+4;").isCorrect) // prints 'true'
  }
}
于 2015-06-01T14:06:42.817 回答