A better way to rotate columns of a matrix independently

Viewed 146

As part of my journey to learn j I implemented a technique for computing the area of a polygon I came across in Futility Closet. I came up with a solution, but it's quite inelegant, so I'm interested in better methods:

   polyarea =: -:@((+/@((1&{&|:)*(0{&|:1&|.)))-(+/@((0&{&|:)*(1{&|:1&|.))))
   y =: 2 7 9 5 6,.5 7 1 0 4
   polyarea y
20

This technique rotates one column and takes the dot product of the columns, then does the same after rotating the other column. The area is half the difference of these two results.

Interested in suggestions!

1 Answers

I think that their technique boils down to using the determinant to find the area of the polygon http://mathworld.wolfram.com/PolygonArea.html

But using the Futility Closet technique I would first close the polygon by adding the first point to the end.

   y =: 2 7 9 5 6,.5 7 1 0 4
   close=: (, {.)  

close is a hook that takes the first pair and appends it to the end

Then take the determinants two points at a time, which is essentially what they are doing with their columns and rotations

   dets=: 2 (-/ . *)\ close  

dets takes the determinant of each pair of points - result is negative if the points are in clockwise order

Then take those values and process for the answer.

   clean=: |@:-:@:(+/)   

clean sums up the determinants, divides by 2 and returns the absolute value of the result.

   clean @: dets y
20

To see the result in complete tacit form we can lean on the f. adverb (Fix) to flatten our definitions.

   clean @: dets f.
|@:-:@:(+/)@:(2 -/ .*\ (, {.))

It is just a different way of looking at what they are doing, but it allows J to use the . conjunction (Dot Product) and \ adverb (Infix) to handle all of those rotations with determinants.

Hope this helps.

Related