Programming Problems That
Illustrate Reuse
Dr. William Mitchell
LSU-Shreveport
My Motivation
Having taught the Software Engineering
Project Course for several years, I approached
the assignment last summer of teaching Java
as a second language in the major’s
programming sequence with the motivation to
impress upon the class the opportunity that
Java offers to solve problems with an eye to
reusing the classes generated.
One of my students dropped a problem into my
lap that I recognized could make the point.
The goal of this board game is to
manipulate the red piece to the position
now occupied by the four yellow pieces.
Initial state-->
Neighbor states
There are 6 different initial moves (only blue
pieces can move, and the vertical blue piece
has two moves--top two blue moves not shown)
Once a blue piece adjacent to a
yellow piece is moved, the yellow
pieces can be re-distributed (not all
pictures are neighbors).
The solution strategy was to employ Wirth’s backtracking algorithm (depth-first recursive search). I
partitioned the problem into GameStates, represented
by the different diagrams and I searched for the
solution state (cells row 3 and row 2, columns 4 and
columns 5 all RED, numbering rows from the bottom
and columns from the left). The algorithm starts in the
initial state, asks if it is the solution state, else creates a
new state if possible. Either the new state is a solution
or another state can be created. Either the solution
state is encountered among those created, or the point
is reached at which no new states can be created.
Certain problems have to be dealt with.
I defined two GameStates to be neighbors if one could
be converted into the other by moving a single piece.
I then constructed a nextNeighbor method to cycle
through the neighbors of any state.
To avoid loops, I needed a way to determine if any
created GameState had previously been created. I
seized upon the two empty squares as a method for
partitioning all the GameStates and used them to key
a lookup table into which I placed all visited states. A
not-previously-visited neighbor state became the
next candidate for a solution when a non-solution
GameState was found.
When a solution was found, I needed to recount the
path taken to the solution, so I recorded the path in a
linked list as I snapped back from the tail recursion.
The main class, PlayGame, therefore creates the
initial instance of GameState, tests each state for
solution and if not, recursively calles for the
generation of a new state. It declares a global array
to hold the link lists of visited states and received a
solution in the form of a linked list of GameStates.
To this class I added a routine that refined the
solution by cutting out “ox-bow”loops, and a display
routine that prints out a list of moves from initial to
terminal state. PlayGame is concerned with the
search space of GameStates. It doesn’t care what
the game is.
The GameState class knows that the game involves a
rectangular board and various pieces. Its
constructors build a board with the pieces in their
initial positions, or create a new state from a given
GameState instance.
Each GameState instance owns a GameBoard
instance that encapsulates how the pieces are
registered on the board. The GameState class uses a
square number to identify the location of a piece and
the GameBoard takes care of determining which
squares are occupied and where the two empty
squares are. Each GameState owns an array of
pieces. The abstract class Pieces provides fields for
color and location, but each individual piece class
provides methods for determining what, if any, moves
that piece can make (zero, one or two). Pieces
determine their move possibilities upon the creation
of the GameState by asking the GameBoard for the
availability of adjacent empty squares and store the
moves as one or more of ‘N’, ‘S’, ‘E’, or ‘W’. Two
GameStates are equal if their boards are identical.
Each GameState instance has a state ID generated
from a class field counter, and a Neighbor counter to
record how many times it has been asked to
generate a neighbor state. The Neighbor state is
generated by stepping through the piece array and
making each move in sequence that each piece can
make. A GameState constructor creates the
Neighbor state as the state existing after the
specified move is made. The GameState class also
has the boolean methods equals() and
isNeighbor(). The GameState class is thus
concerned about creating new states by making
valid moves, but has no knowledge of how moves
are made nor of the fact that different pieces have
different rules for making moves. It knows only that
in each state a certain number of pieces report that
they can make a specified number of moves.
The GameBoard class answers questions about the
state of a square at a given distance and direction
from a reference square. It can also provide square
names. It is free to code each square as it chooses. It
knows nothing about the nature of the pieces or how
they use the codes it returns.
Each piece knows how to determine if it can move
(how to ask the GameBoard if the requisite squares
are free) and stores its move possibilities. It also
stores its move history in a stack using the GameState
ID that corresponds to that move. When backtracking
occurs, each piece can return itself to its earlier
position.
Decomposing the problem into four classes permitted
me to change the board dimensions, the number of
pieces, and the initial position of those pieces in the
GameState class. I then created a new piece class,
Queen, with its own rules of movement. I then changed
the registration method in GameBoard so that it coded
not only each piece’s position on the board but how
many “shadows” crossed each square (each time a
piece was registered, the shadow count on row and file
and diagonals was incremented). Queens preferred to
move from a square with high shadow count to one with
a low shadow count. I then had to change the win()
routine from testing to see if the RED piece was located
in its final position, to determining if each row had only
one queen. I did not care about the steps taken to move
seven of the Queens from the first row to other rows, but
those instructions were available.
In the last SIGCSE Bulletin (32,1) Robert Noonan
presents a paper entitled “An Object-Oriented View of
Backtracking.” He gives the Java code for using the
Backtrack algorithm as an interface and the
java.util.Enumeration class to hold the moves to
solve both the Eight Queens problem and the
Knight’s tour. I had not seen this paper, but then
neither had last summer’s Java class been
introduced to the enumeration class or interfaces.
Noonan also intends to illustrate reuse (of the
interface) but the two problems both use square
boards and consist of placement of pieces of a single
type. My illustration solves dramatically different
board problems within the same conceptual
framework and permits refinement of the solution
found via backtracking.
Noonan laments that fact that the backtracking
algorithm is virtually ignored in popular programming
and data structures texts. I agree and have therefore
incorporated a prior application of recursive search in
my Java as a second language course this semester.
This is the solution of the letter arithmetic puzzles. I
pose and provide most of the code for addition and
ask that the students think about how to implement so
as to minimize the changes needed for subtraction.
Letter addition is solving
WIRE
+ MORE
MONEY
by substituting the same digit for each letter so as
to produce a valid arithmetic fact.
Since there are 8 distinct letters, there are 10!/2!
substitution patterns for E,I,M,N,O,R,W,Y. We can find
a solution with eight nested for loops that implement a
depth-first search of the tree
E = 0..9 {I = 0..9 & !(I==E)
{M = 0..9 & !(M==E) & !(M==I)
{….
{test substitution pattern}….
A more intelligent search incorporates facts about the
relationships of the values of the letters that can be
deduced from their location in columns. In this case, we
know that M is 1 because it is the value of the carry out of
the 4th (103) column. We then know that
W + M + Carryin = O + 10. Thus if Carryin is 0, we have
W + 1 = O +10, whence W=9 and O= 0, or if Carryin is 1,
W + 1 + 1 = O + 10, and W=8 and O=0 or W=9 and O=1.
Since we know that M=1, we can deduce that O=0.
In general, each column represents four equations
determined by the possible values of Carryin and
Carryout. The problem can be solved by searching for
substitutions which satisfy these equations,
simultaneously. A valid problem can have at most 10
distinct letters and may have more than one solution
(this example has fie different solutions).
I assign the students to write the problem class that
inputs the three words and tests to see if they
compose a valid problem. This class also provides
methods to set a solution (the list of digits that
corresponds to the alphabetical list of distinct letters)
and to obtain a column of letters from the three
words. Since all of the character and string
manipulations are concentrated in this class it also
provides the methods to display the problem and its
solution.
I provide the solution class that starts with the highest
column, sets the solution string to blanks, and makes a
recursive call to a static method that tries to make a valid
assignment to the letters in its column. If successful, it
updates the solution string and make a call to continue
making assignments to letters in the next lower column.
Otherwise it returns to its caller to see if an alternative
assignment can be made in the previous column. As in the
eight queens problem, if assignments can be made in
every column down to the units column, then a solution is
found. Since the highest column has Carryout of 0, it
generates two equations dependent upon its Carryin
values. The search for candidate assignments is made by
creating new instances of an Equation class, each
initialized with a pointer to the problem instance
containing the current partial solution, the column number,
and the Carryin value. Each instance has an allocate
method that returns true if it can find another assignment
and update the partial solution string.
The problem class knows nothing about the kind of
arithmetic that is being solved. The solution class
instantiates an instance of a problem and commences
the recursive descent to find a complete solution string,
and it doesn’t know anything about the letters involved
or the partial solutions being generated. It knows only
that it must create an Equation instance for each of two
possible values of Carryin and pass to each as the value
of Carryout the value assumed for Carryin by its caller.
The Equation instance know what equation (addition or
subtraction) it is trying to satisfy, and it must cycle
through the permutations of available digits for
allocation to the unassigned letters in this column.
Thus the Equation class previews the GameState class
and its allocate method behaves like the nextNeighbor
method. The solution class anticipates the PlayGame
class. Letter Arithmetic precedes the game by a month.
Conclusion
The essence of good design is that it permits
modifications of the kind most likely to be required
in the future. However, when learning to program
students seldom think about any problem other
than the specifics of the one assigned. I (and other
instructors) have sought to devise problems that
dramatically illustrate the power of good design by
quickly and easily adapting one problem’s solution
into the solution of a seemingly dissimilar
problem. The designer’s ability to abstract the
characteristics of the initial problem permits the
design of its solution to reveal the similarity of the
whole class of problems related to the initial one.
This presentation and the Java code for the
implementation of the classes discussed in this talk
as well as a recent paper focused on teaching about
code reuse when teaching Java can be found on the
author’s website:
204.196.51.10
© Copyright 2026 Paperzz