prady
prady

Reputation: 593

how do I chain the custom logic using scala?

I am trying to achieve the calculation of area of polygon using scala

Reference for Area of Polygon https://www.mathopenref.com/coordpolygonarea.html

I was able to write the code successfully but my requirement is I want the last for loop to be chained within points variable like other map logics. Map is not working because output of list is (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))

Upvotes: 1

Views: 144

Answers (2)

hoyland
hoyland

Reputation: 1824

You're looking for a sliding and a foldLeft, I think. sliding(2) will give you lists List(i, i+1), List(i+1, i+2),... and then you can use foldLeft to do the computation:

val s = points.sliding(2).foldLeft(0){ 
  case (acc, (p1, p2)::(q1, q2)::Nil) => acc + p1*q2 - p2*q1 } 

If I read the formula correctly, there's one additional term coming from the first and last vertices (which looks like it's missing from your implementation, by the way). You could either add that separately or repeat the first vertex at the end of your list. As a result, combining into the same line that defines points doesn't work so easily. In any case, I think it is more readable split into separate statements--one defining points, another repeating the first element of points at the end of the list and then the fold.

Edited to fix the fact that you have tuples for your points, not lists. I'm also tacitly assuming points is a list, I believe.

Upvotes: 1

Gertjan Assies
Gertjan Assies

Reputation: 1900

how about something like (untested)

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

Upvotes: 0

Related Questions