我正在尝试使用scala
来实现多边形面积的计算多边形区域参考https://www.mathopenref.com/coordpolygonarea.html
我能够成功编写代码但我的要求是我希望将最后一个for循环链接到点变量中,就像其他地图逻辑一样。地图不起作用,因为列表的输出是(N-1)
var lines=io.Source.stdin.getLines()
val nPoints= lines.next.toInt
var s=0
var points = lines.take(nPoints).toList map(_.split(" ")) map{case Array(e1,e2)=>(e1.toInt,e2.toInt)}
for(i <- 0 until points.length-1){ // want this for loop to be chained within points variable
s=s+(points(i)._1 * points(i+1)._2) - (points(i)._2 * points(i+1)._1)
}
println(scala.math.abs(s/2.0))
答案 0 :(得分:1)
我认为您正在寻找sliding
和foldLeft
。 sliding(2)
会为您提供List(i, i+1), List(i+1, i+2),...
列表,然后您可以使用foldLeft
进行计算:
val s = points.sliding(2).foldLeft(0){
case (acc, (p1, p2)::(q1, q2)::Nil) => acc + p1*q2 - p2*q1 }
如果我正确阅读了公式,那么还有一个额外的术语来自第一个和最后一个顶点(顺便说一句,它看起来像你的实现中缺少的那样)。您可以单独添加,也可以重复列表末尾的第一个顶点。因此,组合到定义points
的同一行并不容易。在任何情况下,我认为它更具可读性,分为单独的语句 - 一个定义points
,另一个重复列表末尾的points
的第一个元素,然后折叠。
编辑修复了你的点数而不是列表的元组。我相信,我也默认假设points
是一个清单。
答案 1 :(得分:0)
如何(未经测试)
val points2 = points.tail :+ points.head // shift list one to the left
val area = ((points zip points2)
.map{case (p1, p2) => (p1._1 * p2._2) - (p2._1 * p1._2)}
.fold(0)(_+_))/2