Monday, April 4

Bowling, revisited

I was going through and tagging blog entries and it looks like this one was a latent, unpublished draft.  It's probably best to ignore this post for now....  I am intending to leave this thread of thought alone, for now at least.  See also: http://r-nd-m.blogspot.com/2011/04/tdd-bowling-and-j-revised-part-1.html which I hope will be a better approach.

I am currently writing for an audience of maybe four people, and quite possibly I have disappointed some of them.  Where is the elegance in the code I have been writing?  (Also there was a bug in the blog I posted last, I had 2 >. instead of 2 <. which was horrid.)

Anyways, let's re-invent the bowling scoring code, let's create an array which when all of its numbers have been summed gives us the total score.  In other words, let's have a ten row, three column list of numbers:

   assert 10 3 -: $ framesScore 20#0


   framesScore=: 10 {. 3 ]\ ]

"Now, wait", I can imagine someone saying how do we tell whether a frame is a complete frame or an incomplete frame?

And, the answer is: this function will not tell you that.  This function just gives you numbers you can total up.  And overloading its meaning to attempt to represent incomplete frames seems like bad modularity.  We can use a different function to determine which frames are complete frames -- that does not have to be represented in the scores themselves.

All we are doing here is finding some numbers to add up, let's not make that operation overly complicated.

   assert 0 -: +/, framesScore 20#0

Fine, so far.

   assert 30 -: +/, framesScore 19{.10 0 10

Now we need to identify where each frame starts.  Borrowing from <a href="http://xprogramming.com/articles/j-working-with-henry-richs-example/">Henry</a>:

   framesStart=: 10 {. 0 {~^:a:~  _1 _1  ,~  #\ +  10&~:
   framesScore=: framesStart { 3 ]\ ,&0 0

Whoa... what happened here?

So, first off, I do not really know how test driven development is supposed to work for "enterprise" situations or really any situation where you have pre-existing code.  Are you allowed to just use the code, or are their preconditions?  But, also, I was pretending, in my earlier posts, that I did not understand how Henry's code worked (or even that it existed).  I was wondering if it would just jump out of the process (and it didn't).

But pretending ignorance was getting difficult for me...

So let's go over this code for a bit, since I expect at least one person that might read this blog might not have a computer handy.

   19 {. 10 0 10
10 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

That was just a concise way of expressing a game -- the first ball was a strike, the second was a gutter ball, the third ball turned that frame into a spare and then we gave up so the rest of the balls implicitly had a score of zero.

   10 ~: 10 0 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

This is marking balls where not all of the pins were knocked down all at once.

   (#\ + 10&~:) 19 {. 10 0 10
1 3 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

#\ is 1 2 3 4 5... and if we think in terms of indices it's the index of the next element in the array.  0 is the index of the first element, 1 is the value there and is the index of the second element.  This result 1 3 3 5 6 7.. is "the index of where the next frame starts for each ball if that ball were the start of a frame".  It has some junk values in it, but we do not have to use them (we can select just the useful values).

   (_1 _1,~#\ + 10&~:) 19 {. 10 0 10
1 3 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 _1 _1

We will need those negative values in just a moment.  But if we are thinking of indices, _1 is the index of the last value in an array.

No comments:

Post a Comment