Tuesday, October 25, 2011

Between Two Points with Groovy

I needed to check a ninth grader's math homework related to calculating three things about a line between two points. The assignment was to calculate the distance between two points, the slope of a line connecting the two points, and the midpoint on a line between the two points. Because I was tired after a long day and because I inherently possess the long-advertised software developer "laziness," I decided to write up a quick Groovy script to calculate these numbers for me. There were enough problems to check that I believe I either broke even or even came out a little ahead in terms of time required to write the script versus plugging the numbers into a calculator. I include that script in this post for easy future access when needed. It also provides a chance to look at some Groovy advantages.

findInfoBetweenTwoPoints.groovy
#!/usr/bin/env groovy
// findInfoBetweenTwoPoints.groovy x1 y1 x2 y2

if (args.length < 4)
{
   println "You must enter four numerals: x1 y1 x2 y2"
   System.exit(-1)
}

def inputX1 = args[0]
if (!inputX1.isNumber())
{
   println "${inputX1} is NOT a numeral."
   System.exit(-2)
}
def inputY1 = args[1]
if (!inputY1.isNumber())
{
   println "${inputY1} is NOT a numeral."
   System.exit(-3)
}
def inputX2 = args[2]
if (!inputX2.isNumber())
{
   println "${inputX2} is NOT a numeral."
   System.exit(-4)
}
def inputY2 = args[3]
if (!inputY2.isNumber())
{
   println "${inputY2} is NOT a numeral."
   System.exit(-5)
}

def x1 = inputX1 as BigDecimal
def y1 = inputY1 as BigDecimal
def x2 = inputX2 as BigDecimal
def y2 = inputY2 as BigDecimal

def distanceSquared = Math.pow(y2-y1, 2.0) + Math.pow(x2-x1, 2.0)
def distance = Math.sqrt(distanceSquared)
def slope = x2 != x1 ? ((y2 - y1)/(x2 - x1)) : Double.POSITIVE_INFINITY
if (slope == 0)
{
   println "Horizontal line!"
}
else if (slope == Double.POSITIVE_INFINITY)
{
   println "Vertical line!"
}
def midPointX = (x1 + x2) / 2
def midPointY = (y1 + y2) / 2

println "For points (${x1}, ${y1}) and (${x2}, ${y2}):";
println "\tDistance Between points: sqrt(${distanceSquared}) = ${distance}"
println "\tSlope (m): ${slope}"
println "\tMidpoint: (${midPointX}, ${midPointY})"

This is a fairly basic Groovy script, but it does remind one of how nice it is to strip away the normal ceremony of having a class and methods and all the other overhead to leave a fairly straightforward logic-heavy script. Some nice Groovy-isms are demonstrated including use of the implicit args handle, use of the as keyword to fluently cast the String arguments into BigDecimal instances, use of Groovy's (GDK) String.isNumber(), and use of placeholders in Groovy Strings for greater readability. It is really easy to quickly identify the core of this script, which is the mathematical functions used to calculate midpoint, slope, and distance.

The following screen snapshot shows a couple of examples of running this script on different values.

Conclusion

It says something for ease of use of a scripting language when it's easier to code up a simple script for performing calculations than it is to use a calculator to perform the same calculations manually. Of course, I could have programmed a sophisticated calculator to do the same thing, but I think it was probably easier to code this script than to go find my calculator or learn how to use and program the ninth grader's calculator!

1 comment:

Greg said...

It would be better to practise visualization of the points and do the calculation in your head (seriously)