I'm James Hague, a recovering programmer who has been designing video games since the 1980s. Programming Without Being Obsessed With Programming and Organizational Skills Beat Algorithmic Wizardry are good starting points. For the older stuff, try the 2012 Retrospective.

Where are the comments?

twitter / mail / newsfeed

Revisiting "Tricky When You Least Expect It"

Since writing Tricky When You Least Expect It in June 2010, I've gotten a number of responses offering better solutions to the angle_diff problem. The final version I presented in the original article was this:

angle_diff(Begin, End) ->
   D = End - Begin,
   DA = abs(D),
   case {DA > 180, D > 0} of
      {true, true} -> DA - 360;
      {true, _}    -> 360 - DA;
      _ -> D

But, maybe surprisingly, this function can be written in two lines:

angle_diff(Begin, End) ->
   (End - Begin + 540) rem 360 - 180.

The key is to shift the difference into the range -180 to 180 before the modulo operation. The "- 180" at the end adjusts it back. One quirk of Erlang is that the modulo operator (rem) gives a negative result if the first value is negative. That's easily fixed by adding 360 to the difference (180 + 360 = 540) to ensure that it's always positive. (Remember that adding 360 to an angle gives the same angle.)

So how did I miss this simpler solution? I got off track by by thinking I needed an absolute value, and things went downhill from there. I'd like to think if I could rewind and re-attempt the problem from scratch, then I'd see the error of my ways, but I suspect I'd miss it the second time, too. And that's what I was getting at when I wrote "Tricky When You Least Expect It": that you never know when it will take some real thought to solve a seemingly simple problem.

(Thanks to Samuel Tardieu, Benjamin Newman, and Greg Rosenblatt, who all sent almost identical solutions.)


Caught-Up with 20 Years of UI Criticism
If You're Not Gonna Use It, Why Are You Building It?
Don't Distract New Programmers with OOP
Exploring Audio Files with Erlang
Accidental Innovation, Part 3