From: tr.17687@z991.linuxsc.com   
      
   Ben Bacarisse writes:   
      
   > Tim Rentsch writes:   
   >   
   >> Ben Bacarisse writes:   
      
   For reference here is my earlier answer [with return type changed   
   to 'bool']:   
      
    bool   
    is_circularly_between( T a, T b, T c ){   
    return a <= c ? a <= b && b < c : a <= b || b < c;   
    }   
      
   >>> [In contrast to the definition above] I   
   >>> chose to use a recursive call, because I though it explained the   
   >>> non-trivial case more clearly (but I bet I am pretty much the only   
   >>> one who thinks that).   
   >>   
   >> I want to add something here to my earlier comment. The idea of   
   >> using a recursive call reflects a deeper understanding of what   
   >> "circular regions" are. If one has already assimilated that   
   >> understanding then I think the recursive call is "more obvious",   
   >> in the sense that it takes less thought, or I might say less   
   >> additional thought. I didn't have that background (and didn't   
   >> develop it while solving the problem) so for me the cruder but   
   >> more direct approach was easier to see. Bottom line, I don't   
   >> think either formulation is uniformly "easier to understand" than   
   >> the other; it depends on one's background (or ability to develop   
   >> a suitable understanding on the fly, which in this case I did not   
   >> possess).   
   >   
   > For me, the negated recursive call was a sort of "ah ha!" moment. I   
   > was ploughing forwards trying to work out this and that case when a   
   > light-bulb went off.   
      
   For reference here is your recursive version:   
      
    bool is_circularly_between(T start, T end, T i) {   
    return start <= end ? start <= i && i < end   
    : !is_circularly_between(end, start, i);   
    }   
      
   > Above I say "it explained the non-trivial case more clearly" but   
   > that's lazy wording and does not capture what I meant. Rather than   
   > explaining anything, I want code that is easy to verify. I want,   
   > with just a little thought, to know it's right.   
      
   Even after understanding the "ah ha!", I am still not entirely happy   
   with this version. Even though I know the trick, there is still a   
   mental slowdown around the negated recursive call. I can see that   
   it works, but it takes a little bit of mental effort each time.   
      
   Thinking a little more about how to write an answer, I came up with   
   this:   
      
    extern bool is_circularly_between( T, T, T );   
    extern bool is_circularly_outside( T, T, T );   
      
    bool   
    is_circularly_between( T start, T limit, T x ){   
    if( start <= limit ) return start <= x && x < limit;   
      
    return is_circularly_outside( limit, start, x );   
    }   
      
    bool   
    is_circularly_outside( T start, T limit, T x ){   
    if( start <= limit ) return x < start || limit <= x;   
      
    return is_circularly_between( limit, start, x );   
    }   
      
   For me this version is mentally smoother than the negated directly   
   recursive call. Part of the reason for that is having the two   
   complementary functions shows the duality more explicitly. Of   
   course I never would have gotten here if not for your insight; even   
   so, I'm inclined to prefer this version on the metric of which is   
   easier to convince myself that it's right.   
      
      
   >> This problem provides an example where it helps to see both   
   >> approaches to solving the problem, to see how they relate to each   
   >> other, but also to give an appreciation for the power of having   
   >> more advanced tools available in the mental toolbox.   
   >   
   > I've got rather fond of it as a question. I don't conduct any   
   > interviews anymore or I would be tempted to use it.   
      
   It's a great question. I'm glad you posted it.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|