Stuff I Didn’t Publish This Year
December 12, 2007 Ted Holt
Note: The code accompanying this article is available for download here.
My wife and I recently visited our local Cracker Barrel, which is one of our favorite restaurants. While we were waiting for our food, I picked up the peg game that unfailingly occupies patrons at the tables of that establishment and, for the umpteenth time, failed to solve it.
The Peg Game
In case you’re not familiar with a peg game, here’s how it works. The board has 15 holes arranged in a triangle and 14 of the holes are occupied by pegs. To move, you jump a peg over an adjacent peg and land in the unoccupied hole on the other side, then remove the jumped peg from the board. The object of the game is to leave one peg on the board. It should be easy, but I can’t figure it out. I always leave at least two or three pegs, which places me in the ignoramus category, I think.
As my wife and I sat there, trying to think of something to talk about other than the kids, it occurred to me that, while I’m too stupid to find a solution to the puzzle, I’m not too stupid to make a computer find a solution. A week or two later, I threw together an RPG program to print all possible solutions to the peg game. If you’re interested, download it here.
With the number one hole left blank, here are four solutions.
Each move is a six-digit number made of a two-digit beginning position (From), a two-digit position to be jumped (Over), and a two-digit ending position (To). The first move of the first solution, 040201, means “the peg in hole 4 jumps the peg in hole 2 and lands in hole 1.”
I numbered the holes one to 15, like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
According to my program, there are 29,760 solutions to the peg game. I can’t find even one of them. Ignoramus is too generous.
Indicators: *ON, *OFF, *NEITHER?
One of the first things I learned about RPG was that an indicator can be either off or on. This information was crucial because I was using the RPG II compiler on a System/3 Model 12. We didn’t have any of these fancy IFxx, CABxx, CASxx, and DOxxx op codes or *INxx variables.
Fast-forward to the 21st century and witness how much we have progressed. Now a variable can be off, on, or neither off nor on. A three-valued indicator? Have we arrived or what? Here’s how it’s done.
Declare a two-byte character variable.
D SomeVar s 2a inz(*off)
SomeVar is *ON if it holds two ones, *OFF if it contains two zeros, and is neither *ON nor *OFF if it has one one and one zero. Now you can code expressions like these:
if SomeVar = *on; DoWhatever(); endif; if SomeVar = *off; DoThis(); endif; if SomeVar <> *on and SomeVar <> *off; DoSomething(); else; DoSomethingElse(); endif; if SomeVar = *on or SomeVar = *off; DoSomething(); else; DoSomethingElse(); endif;
Don’t those last two ifs look weird? Believe it or not, it’s possible for the else branches to execute. And no, before you ask, I’ve never found a use for this technique.
Store a Binary Tree in an Array
Years ago, when I was earning my computer science degree, I used linked lists to implement binary trees in Pascal programs. Since linked lists don’t work too well in RPG, it may be better to use an array instead. “How does that work?” I hear you ask.
Consider the following binary tree:
Joe / \ / \ / \ / \ Bob Sam / \ / \ / \ / \ / \ / \ Jim Bud Don Abe
The same can be stored as an array. The left leaf of node nis in element 2n. The right leaf is in element 2n + 1.
To find the parent of a node, divide the element number by two and throw away the remainder.
I have known people who took pride in writing a program as concisely as possible. If memory serves me correctly, the old Data Network magazine, the forerunner to Midrange Computing, often presented programming problems in which the object was to achieve the desired output with as few lines of RPG or OCL as possible.
I still like to keep programs short, but not at the expense of readability. Some shortcuts are clearly better, at least in my opinion. For example, I much prefer this:
/free *in25 = not *in25;
/free if *in25; *in25 = *off; else; *in25 = *on; endif;
I offer the following logical shortcuts with a healthy dose of skepticism that they are better than their longer equivalents.
Problem 1: Verify that an order is ready for shipment (i.e., all lines of an order are complete). A line is complete if the status code is E.
ReadyToShip = *on; dow '1'; read OrdLine; if %eof(); leave; endif; if Status <> 'E'; ReadyToShip = *off; endif; enddo;
ReadyToShip = *on; dow '1'; read OrdLine; if %eof(); leave; endif; ReadyToShip = ReadyToShip and Status = 'E'; enddo;
One line has replaced three lines. Here’s a similar example.
Problem 2: Is at least one line of an order ready to ship?
OneLineIsReady = *off; dow '1'; read OrdLine; if %eof(); leave; endif; if Status = 'E'; OneLineIsReady = *on; endif; enddo;
OneLineIsReady = *off; dow '1'; read OrdLine; if %eof(); leave; endif; OneLineIsReady = OneLineIsReady or Status = 'E'; enddo;
What do you think? Better or worse?
While I’m on the subject of logic, here’s a bit of code from a program I worked on recently. Do you see the logic error?
C SOMEKEY CHAIN SOMEFILE 97 C *IN97 IFEQ '0' C *IN97 DOWEQ '0' ... more stuff C ENDDO C ENDIF
Enjoy the Holidays
My family and I will soon be celebrating Christmas. I used to muddle through the Christmas season with a bit of cynicism, relating to the words of Henry Wadsworth Longfellow.
And in despair, I bowed my head:
But I finally figured out that misery, cynicism, and other negative emotions don’t solve any problems. Just the opposite is true. There is enough misery in the world without my choosing to be miserable, too.
So now I enjoy Christmas. I enjoy the special songs and carols, the lights and decorations, the excitement in my children’s faces, the gatherings with family and friends. I receive more pleasure from giving than from getting. These days I think on other words from Longfellow:
Then pealed the bells more loud and deep:
Whatever holidays you celebrate, if any, I wish for you a season of happiness and peace. I hope that 2008 will be the year when everyone on earth becomes as happy as I am.
Answer to the logic question:
Since do-while is a top-tested loop, the if is unnecessary.