Ripple Effect

Bachelor Thesis
Ripple Effect
Wilfried Pasquazzo
[email protected]
30 August 2008
Supervisor: Univ.-Prof. Dr. Aart Middeldorp
Abstract
Ripple Effect is a logic puzzle played on a rectangular field that is divided in
multiple rooms of varying size and shape. The target is to fill in numbers
without breaking any of the game rules. Although the task looks simple it
belongs to the realm of NP-complete problems. The implementation of a solver
that can automatically solve any Ripple Effect puzzle, a generator that supplies
the user with new instances of the problem and a graphical user interface to
solve and design Ripple Effect puzzles manually is the scope of this thesis.
Contents
1 Introduction
1.1 Motivation
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 Ripple Effect
2.1 What is Ripple Effect? . .
2.2 Structure of the Puzzle . .
2.2.1 Rules . . . . . . .
2.2.2 Solving Strategies
2.2.3 Difficulty Rating .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
.
.
.
.
.
2
2
2
3
3
3
3 Implementation
3.1 Data structure . . . . . . . . . . . . . . . . . . .
3.2 File format . . . . . . . . . . . . . . . . . . . . .
3.3 Solver Algorithms . . . . . . . . . . . . . . . . .
3.3.1 Simple Solver . . . . . . . . . . . . . . . .
3.3.2 Extended Simple Solver . . . . . . . . . .
3.3.3 “What-If” Solver . . . . . . . . . . . . . .
3.4 SAT Solver . . . . . . . . . . . . . . . . . . . . .
3.4.1 SAT Solver Input . . . . . . . . . . . . . .
3.4.2 Defining Variables . . . . . . . . . . . . .
3.4.3 Ensuring Exactly One Number Per Cell .
3.4.4 Encoding the Rules . . . . . . . . . . . .
3.4.5 Assign Predefined Values . . . . . . . . .
3.4.6 Predicting Needed Variables and Clauses
3.4.7 How SAT Solving Works . . . . . . . . . .
3.4.8 Advantages of SAT Solving . . . . . . . .
3.5 Puzzle Generator . . . . . . . . . . . . . . . . . .
3.5.1 Generate Rooms . . . . . . . . . . . . . .
3.5.2 Ensure Unique Solution . . . . . . . . . .
3.5.3 Set the Maximum Difficulty Level . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
6
7
7
8
8
10
11
11
11
11
12
12
12
13
13
13
16
17
4 GUI
4.1 Swing . . . . . . . . . . . .
4.2 Structure of the GUI . . . .
4.2.1 Playfield . . . . . . .
4.2.2 Menus and Toolbars
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18
18
18
19
20
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Performance Measuring
24
5.1 Solver Performance . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.2 Generator Performance . . . . . . . . . . . . . . . . . . . . . . . . 25
iv
6 Summary
26
Bibliography
27
A Proof of NP-Completeness
28
1 Introduction
Solving Japanese logic puzzles has become a hobby for people around the globe.
Many newspapers and magazines added the famous puzzle Sudoku to their
crossword section and introduced their readers into the world of numeric logic
puzzles. “Ripple Effect” is a similar but mostly unknown puzzle invented by
Nikoli Ltd. [2], the publisher of Sudoku.
The target of this thesis is to develop a program that helps the user to
solve Ripple Effect puzzles. It should have a graphical user interface to allow
interactive creation and solving of puzzles and should implement algorithms
that allow automated solving and generation of puzzles of varying difficulty.
The structures to represent a Ripple Effect puzzle in a program, if and how
puzzles can be automatically solved and new ones generated, how effective they
are and what this could mean for the future of Ripple Effect will be presented
in this thesis.
1.1 Motivation
Although the task of solving Ripple Effect sounds rather simple: “Fill into
every empty field of a rectangular grid one number such that two properties
hold for the completely filled out grid.” it belongs to the realm of NP-complete
problems, as will be shown in Appendix A.
The generation of new puzzles for the user is complicated too, because the
structure of Ripple Effect puzzles seems to be random and small changes to it
will most likely result into an unsolvable puzzle.
Finally these algorithms need to be implemented and combined with a user
friendly GUI that grants easy access to this functionality and allows for manual
solving and creation of puzzles.
This thesis will therefore present algorithms that can quickly solve parts of
Ripple Effect puzzles by using strategies of human solvers and an elegant way
to harness the power of a satisfiability solver to solve any puzzle, even if it
has multiple solutions. To generate new puzzles an algorithm that splits the
task into three steps was designed: generating the puzzle structure, ensuring a
unique solution and then adjusting the puzzle to fit a certain difficulty level.
The program is implemented in the popular programming language Java [4]
and therefore will run on most operating systems and hopefully increase the
general interest in Ripple Effect puzzles after its release.
1
2 Ripple Effect
2.1 What is Ripple Effect?
Ripple Effect (also known under the name “Hakyuu”) is a logic puzzle from
Japan. Nikoli got famous for publishing Sudoku, another logic puzzle, that is
somehow similar to Ripple Effect.
It is played (like most Nikoli puzzles) on a rectangular grid. Some of the
cells of the grid are joined together and some of them are filled with a number.
The target is to fill numbers into the empty cells such that the resulting grid
complies to certain rules.
The first book dedicated to Ripple Effect and consisting of 98 puzzles was
published 2005 in Japan [3].
2.2 Structure of the Puzzle
Figure 2.1: Left: Ripple Effect puzzle, Right: Solution
A Ripple Effect puzzle consists of cells that are arranged in a rectangular
grid. These cells are grouped into “rooms” in a way that each cell belongs
to exactly one such room and all cells of a room are directly connected and
therefore neighbors. Many published puzzles are square in size, although that
isn’t a requirement for Ripple Effect.
In addition, parts of the solution may already be given by numbers between
1 and the maximum size of the room in some of the cells. This is most likely the
2
2.2 Structure of the Puzzle
case if they are needed to guarantee a unique solution or reduce the difficulty
of the puzzle.
2.2.1 Rules
Ripple Effect has only two simple rules:
Rule 1
If a number n appears more than once in a row or column, there must be at
least n cells between these numbers. E.g. a 4 has to be at least at a 4-field
distance to any other 4 in the same row or column.
Rule 2
A room consisting of n cells has to have all the numbers from 1 to n assigned to
its cells. E.g. a room that consists of 4 cells has to be filled with the numbers
1, 2, 3 and 4.
Solution
The puzzle is solved, if every cell is filled with a number without breaking any
of the two rules. See Figure 2.1 for an example of a correct solution.
2.2.2 Solving Strategies
A good way to solve Ripple Effect puzzles manually is to first fill the cells that
can obviously only hold one value, e.g. cells in rooms of size 1 can only hold
the number 1 and the last empty cell of a room can only hold the value that
is still missing in that room. This will probably add some new constraints to
values that can be entered in the surrounding cells.
If no easy to fill cells are left, a good approach is to choose one cell after
another and check for each, if there can only one value be entered without
directly breaking a rule. An alternative approach is to check for each room, if
any of the missing numbers can only be placed in one cell of the room without
breaking rules.
Iterating between these two simple techniques will provide the solver with
the correct solution to many of the easier Ripple Effect puzzles available today,
but they may fail on harder puzzles and aren’t useful for solving puzzles that
have more than one possible solution. In these cases guessing some cell values
and checking if those guesses lead to a correct solution may be necessary.
2.2.3 Difficulty Rating
There exist some indicators that can help to estimate the difficulty of a Ripple
Effect puzzle before solving it.
The first and probably best indicator is (of course) the dimension of the
puzzle. Bigger Ripple Effect puzzles will tend to take longer to solve than small
ones.
3
2 Ripple Effect
A second indicator is the average size of the rooms of the puzzle. Puzzles
with smaller rooms are often easier to solve, because there exist not as many
permutations of the value assignments for the cells of the room. Additionally
the smaller numbers result into rather local and less dependencies on the values
of other cells of the puzzle.
Finally the number of prefilled cells can also be an indicator of difficulty. If
there are many prefilled cells it may be easier to fill the others.
But to determine the actual difficulty, the player will still have to try to solve
the puzzle.
4
3 Implementation
The aim of this thesis is to implement a program that is capable of solving
Ripple Effect puzzles automatically, generating new Ripple Effect puzzles and
providing a nice GUI (graphical user interface) that allows easy access to its
functions. In addition, the user should be allowed to solve and design puzzles
manually and to save his progress.
The choice of the implementation language fell on Java, because it is a popular
and hardware independent programming language and the writer of this thesis
has most experience in this language.
In the following sections various implementation details will be presented
along with the specially for Ripple Effect created algorithms to solve and generate puzzles. But first we’ll take a look at the representation of a Ripple Effect
puzzle in the program.
3.1 Data structure
To implement the demanded program a qualified data structure has to be defined. The chosen approach in this implementation consists of three layers (see
Figure 3.1).
The inner layer called “PuzzleData” holds the actual information about the
puzzle size, the shape and position of the rooms, the predefined cell values
(that can’t be changed by the user) and the values entered by the user. No
checks for validity or consistency of the data are made in this layer. The data
structure in this implementation consists of three two-dimensional arrays of the
same size as the puzzle grid. The first array contains the entered cell value,
the second array contains a number declaring which room the cell belongs to
(same numbers equals same rooms) and the third array declares if an entered
cell value is predefined or entered by the user.
The middle layer called “PuzzleRules” adds the editor functionality (like
merging of cells into a new room) and keeps the data in the inner layer consistent
by using extensive validity checks on any calls to the underlying layer. E.g. it
is checked if the cells that will be merged are neighbors and if an entered cell
value is bigger than the size of the room it is in. It also adds functionality for
application of solutions generated by any of the solvers.
The outer layer called “PuzzleGame” adds the non-vital functionality for
undo/redo of the changes made and pause/resume of the current gaming session.
To keep track of the changes made the class TimeLine is used to record any
cell that was changed by storing its coordinates, old value and new value. The
class Timer additionally provides the puzzle with a stop watch that will be
started/stopped if the puzzle is resumed/paused.
5
3 Implementation
Figure 3.1: The design of the data structure of Ripple Effect
This layered approach allowed for fast and easy exchange of certain functionality of the puzzle without worrying about other functions that may be
affected by made changes. It also hides the complexity of the inner layers,
which increases understandability of the source code.
After having designed the data structure, a file format that can reliably store
the information has to be defined.
3.2 File format
It is important to allow the user to save and load puzzles to give him/her the
opportunity to save his/her progress, exchange created puzzles with others and
to use already designed puzzles. Although Java comes with extensive support
for serialising classes and data automatically to store them as a compact sequence of bytes, another approach was taken for Ripple Effect, to allow the
created files to be easily read by humans and/or used by other programs.
Ripple Effect puzzles have a rather simple structure, therefore the needed
information can be encoded as a sequence of integer numbers stored in ASCII.
A saved puzzle consists of two parts.
The first is a header consisting of two integer numbers, that represent the
width n and height m of an n × m sized puzzle. The second part is a list of
6
3.3 Solver Algorithms
n × m integer pairs which represent the cells of the puzzle. The first number
of each pair is a room identifier. All cells with the same room identifier belong
to the same room in the Ripple Effect puzzle. The second number is the value
that is entered in that room. If it is 0, the cell is empty, if it is positive, the
cell has this value and if it is negative, it is a predefined value that can’t be
changed.
Figure 3.2: A Ripple Effect puzzle encoded as ASCII numbers
For convenience and readability all white-space and punctuation characters
between the numbers are ignored. This allows to write the Ripple Effect files
in a human readable form by arranging the number pairs in rows of the same
width as the encoded puzzle. An example for a Ripple Effect puzzle and its
encoded file can be seen in Figure 3.2.
3.3 Solver Algorithms
To assist the player with solving Ripple Effect puzzles, four solvers of varying complexity were implemented. The first three are designed to mimic the
behaviour of humans. Although this isn’t necessarily an efficient way to solve
Ripple Effect puzzles and will not always lead to success, it allows the use of
these solvers to determine the difficulty level of puzzles by checking if and which
solvers find the solution and therefore makes them valuable for the implementation of a puzzle generator.
The fourth implemented solver uses a satisfiability solver (or SAT solver)
library called “SAT4J” [5] to find the correct solution to any Ripple Effect
puzzle. This is the default solver of the Ripple effect program and it is also
used to determine if a puzzle has one, multiple or no solution.
3.3.1 Simple Solver
The first and simplest solver checks all empty cells of the puzzle one at a time
if they can hold one, multiple or no value without breaking a game rule.
7
3 Implementation
Algorithm 1 Definition of the ’possible(x, y, v)’ function
Require: cell coordinates x, y
Require: possible cell value v
1: if v > roomOf(cx,y ).size() then
2:
return false
3: else if ∃x0 y 0 | roomOf(cx0 ,y 0 ) = roomOf(cx,y ) and (x0 , y 0 ) 6= (x, y)
and cx0 ,y0 = v then
4:
return false
5: else if ∃x0 | x0 6= x and | x0 − x |≤ v and cx0 ,y = v then
6:
return false
7: else if ∃y 0 | y 0 6= y and | y 0 − y |≤ v and cx,y 0 = v then
8:
return false
9: else
10:
return true
11: end if
To check if a value v can be entered into the cell at the coordinates (x, y) the
’possible(x, y, v)’ (see Algorithm [1]) function is used. If v is bigger than the
room size of the cell at (x, y) or there exists already a cell in the same room
with that value or the value already appears within a v-cell distance to left,
right, top or bottom of the cell, the function returns ’false’ else ’true’.
If a cell can hold no value, the puzzle has no valid solution. If it can hold
exactly one value, the value is entered and if it can hold multiple values, the
algorithm goes on and checks the next cell. This procedure is repeated until no
more cell values can be entered this way (see Algorithm 2).
3.3.2 Extended Simple Solver
The Extended Simple solver adds another approach of reasoning about the
value of a cell cx,y . Instead of just checking if the cell can hold only one value,
it checks if a certain value can be placed in only one cell of a room. This is
done by defining a set A of possible entries for cx,y and then removing every
value that can appear in another cell of the same room.
If the remaining set A has exactly one element n, the correct entry for cx,y
is n. If A is empty, the algorithm goes on to the next cell. If A has more than
one element, the puzzle has no correct solution and the algorithm terminates.
The algorithm runs as long as new entries can be made (see Algorithm 3).
3.3.3 “What-If” Solver
The third algorithm for solving Ripple Effect puzzles is called “What-If” solver,
because it works on the principle of trial and error. For each iteration it chooses
an empty cell cx,y of a puzzle P and then defines the set A of possible entries
for cx,y . For each element n of A the puzzle gets copied to a new puzzle Pn and
solved under the assumption that cx,y = n in Pn .
Then all valid solutions are compared. If a cell cx,y has the same value in all
puzzles, this value is entered in the original puzzle P (see Algorithm 4). This
8
3.3 Solver Algorithms
Algorithm 2 Simple solving algorithm
1: progress = true
2: while progress do
3:
progress = false
4:
for all cells cx,y | cx,y = 0 do
5:
A=∅
6:
for i = 1 to roomOf(cx,y ).size() do
7:
if possible(x, y, i) then
8:
A = A ∪ {i}
9:
end if
10:
end for
11:
if A = ∅ then {No possible values}
12:
return Error: ‘No solution exists’
13:
else if A = {n} then {Only one possible value}
14:
cx,y = n
15:
progress = true
16:
else
17:
{Can’t decide what to fill in, therefore do nothing.}
18:
end if
19:
end for
20: end while
Algorithm 3 Extended simple solving algorithm
1: progress = true
2: while progress do
3:
progress = false
4:
run ‘SimpleSolvingAlgorithm’
5:
for all cells cx,y : cx,y = 0 do
6:
A = {n | possible(x, y, n) = true }
7:
for all n ∈ A do
8:
if ∃x0 , y 0 | roomOf(x0 , y 0 ) = roomOf(x, y) and (x0 , y 0 ) 6= (x, y)
and possible(x0 , y 0 , n) then
9:
A = A \ {n}
10:
end if
11:
end for
12:
if A = ∅ then {No possible values}
13:
{Can’t decide what to fill in, therefore do nothing.}
14:
else if A = {n} then {Only one value}
15:
cx,y = n
16:
progress = true
17:
else
18:
return Error: ‘No solution for this puzzle exists’
19:
end if
20:
end for
21: end while
9
3 Implementation
Algorithm 4 What-If solving algorithm
Require: Ripple Effect puzzle P
1: progress = true
2: while progress do
3:
progress = false
4:
for all cells cx,y in P | cx,y = 0 do
5:
A = {n | possible(x, y, n) = true}
6:
B=∅
7:
for all n ∈ A do {solve for all possible entries of cx,y }
8:
copy puzzle P to Pn
9:
c0x,y in Pn = n
10:
Pn = ‘solve Pn with ExtendedSimpleSolvingAlgorithm’
11:
if no Error occurred then
12:
B = B ∪ {Pn }
13:
end if
14:
end for{check for cells that always have the same value}
15:
if B = ∅ then {No puzzles}
16:
return Error: ‘No solution exists’
17:
else {One or more puzzles had no errors}
18:
for all cells cx,y in P | cx,y = 0 do
19:
choose a Pi ∈ B
20:
if ¬∃c0x,y in Pi , c00x,y in Pj | Pj ∈ B and c0x,y 6= c00x,y and c0x,y > 0
then
21:
cx,y = c0x,y in Pi
22:
end if
23:
end for
24:
end if
25:
end for
26: end while
procedure gets repeated as long as new entries can be made.
This algorithm is rather inefficient concerning time and space needed, but
it mimics the human solving strategy of guessing the value of one cell, then
testing if that leads to contradictions or a valid (partial) solution pretty well
and can therefore be used for determining the difficulty for human players to
solve a puzzle.
3.4 SAT Solver
All previously mentioned algorithms are especially designed to solve Ripple
Effect puzzles with unique solutions, because they only assign values to cells if
no other valid assignment is possible. E.g. all puzzles in [3] can be solved by
the Extended Simple solver.
Puzzles with multiple solutions and some very hard unique solution puzzles
instead can be solved by “brute force”, which means to try every possible assignment of values to empty cells until one is found that solves the puzzle.
10
3.4 SAT Solver
An elegant way of brute forcing a problem is to use a satisfiability solver.
SAT solving is an NP-complete problem, but there exist advanced heuristics
to allow the algorithm to first test assignments that have higher chances to be
correct solutions.
This project uses the SAT solving library “SAT4J” [5]. A basic introduction
into SAT solvers and how to transfer a Ripple Effect puzzle into a SAT problem
will be given in the following sections.
3.4.1 SAT Solver Input
SAT solvers work on conjunctive normal forms. This means a problem has to
be converted into one logic expression consisting of possibly negated Boolean
variables that are connected by the Boolean ∨ (or) to terms named clauses.
All these clauses are connected by the Boolean ∧ (and). The solution of the
problem is any assignment of truth values to the variables, such that the whole
term evaluates to true.
3.4.2 Defining Variables
The first task is to define variables that represent the Ripple Effect puzzle that
needs to be solved. Since the only thing that can be changed is the value
assignment of the cells, a mapping like this of cell/value to variable is fast and
easy: vx,y,v := cell at coordinates (x, y) has value v.
If e.g. v1,4,2 is true, the cell at (1, 4) has the value 2.
For a Ripple Effect puzzle grid of width x, height y and biggest room size z
the number of needed variables can be estimated by x ∗ y ∗ z.
3.4.3 Ensuring Exactly One Number Per Cell
The SAT solver doesn’t know of the restriction of exactly one number per cell,
therefore this restriction has to be converted into clauses. Defining an “exactly
one” relation in Boolean logic can be done by splitting it into an “at least one”
and an “at most one” part.
The first part is simply a clause containing all variables, e.g. for a cell at
coordinates (1, 4) with a maximum value of 3 (the room size of the cell), the
clause would be (v1,4,1 ∨ v1,4,2 ∨ v1,4,3 ).
The second part is done by building clauses of any two variables in their
negated form. For the example above this would result into the following
clauses: (¬v1,4,1 ∨ ¬v1,4,2 ) ∧ (¬v1,4,1 ∨ ¬v1,4,3 ) ∧ (¬v1,4,2 ∨ ¬v1,4,3 ).
The number of clauses needed for a cell can be estimated by 1 + z ∗ (z + 1)/2,
with z being the size of the room the cell belongs to.
3.4.4 Encoding the Rules
To guarantee that no two cells on the same row/column within n cells have the
value n (rule 1), an “at most one” relationship is needed between those cells,
as seen in the previous section. The maximum number of clauses needed for a
11
3 Implementation
cell can be estimated by z ∗ (z + 1) with z being the size of the room the cell
belongs to.
To guarantee that no two cells in the same room have the same value (rule 2),
an “at least one” relationship for every possible value for each room is enough,
because this rule combined with the clauses from subsection [3.4.3] lead to an
“exactly one” relationship. The number of additional needed clauses for cell in
a room of size z is therefore exactly 1.
3.4.5 Assign Predefined Values
At last the cells that already have a value assigned to them need to be considered. For each of these cells exactly one clause with one variable needs to be
added, e.g. if the cell at (1, 4) has value 3, the clause is (v1,4,3 ).
3.4.6 Predicting Needed Variables and Clauses
As an example we use puzzle 4 of the book [3]. This puzzle consists of 8×8 cells
combined to rooms of a maximum size of 4 with 8 cells prefilled. This means we
can predict the maximum number of variables needed with 8∗8∗4 = 256 and the
maximum number of clauses with 8∗8∗((1+4∗(4+1)/2)+(4∗(4+1))+1+8) =
2.560. As can be seen, even rather small Ripple Effect puzzles can result into
very high numbers of variables and clauses needed.
3.4.7 How SAT Solving Works
SAT solving is a lively area of research with new algorithms and heuristics
appearing every year. Therefore only a small introduction into some basic
techniques will be given.
A SAT-solver tries to find truth-assignments for all variables, such that at
least one part of each clause is true. If there are clauses with exactly one
variable, the solver will assign the truth value to this variable that evaluates
the whole clause to true. E.g. if the clause under consideration is (¬v1,4,3 ),
v1,4,3 = f alse is assigned.
Now all appearances of that variable that will lead to an evaluation of false
get “eliminated”, because they do not influence the other variables of the clause.
E.g if a clause is of the form (vx,y,z ∨ v1,4,3 ∨ vr,s,t ) the v1,4,3 would be removed,
because it had f alse assigned to it earlier. If a clause has no more variables
after an elimination (it is an empty clause), the SAT problem has no solution
and will report a contradiction.
In addition, all clauses that evaluate to true because they contain the variable
with the assigned truth value, get removed by the SAT solver. E.g. if a clause
is of the form (vx,y,z ∨ ¬v1,4,3 ∨ vr,s,t ) the clause will evaluate always to true,
because v1,4,3 is f alse. Therefore it can be removed without influencing the
result.
Any variable that does not appear in any clauses can be assigned either true
or false.
12
3.5 Puzzle Generator
3.4.8 Advantages of SAT Solving
At first glance it isn’t obvious why a SAT solver is used instead of an especially
for Ripple Effect designed brute force algorithm, especially when looking at the
effort needed to convert a Ripple Effect puzzle into a satisfiability problem.
The answer is, that designing a new brute force algorithm can be tricky. Does
it always give the expected result, even if there is no/many solution(s)? For any
optimizations or changes to the algorithm this question needs to be answered
again and again. Designing the algorithm to work fast when much memory is
available without losing the possibility to run it in low memory environments
can be problematic and error prone too.
These problems don’t appear with SAT solvers, because they are proved to
deliver the correct results, most of them adjust automatically to the available
amount of memory and they can easily be exchanged with other implementations, because their input format is always the same. They incorporate many
heuristics and optimizations that lead to very short solving times in most cases.
Especially with “simple” problems like Ripple Effect where the dependencies
of variables are more or less local (meaning that variables representing values
at one end of the puzzle grid don’t have direct dependencies on variables of
the other side) a SAT solver can find contradictions or possible eliminations
very fast, which leads to solvability of huge Ripple Effect puzzles of more than
a thousand cells (resulting in many thousand variables and clauses) within
seconds.
3.5 Puzzle Generator
To generate new puzzles that have a unique solution, a three step approach is
taken. The first step is the placement of rooms in the grid in a way, that at
least one correct solution exists. In the second step numbers are filled in until
the puzzle has a unique solution. The third and last step is to place additional
numbers to comply to a given difficulty level.
3.5.1 Generate Rooms
The generation of an empty puzzle that has at least one solution isn’t a trivial
task. If the rooms are randomly placed on the grid the resulting puzzle may be
unsolvable and the only way to find out if such a randomly generated puzzle
has a solution would be to solve it.
A better approach is to construct the rooms of the puzzle at the same time
as the solution to the puzzle. This way the time consuming task of checking if
a solution exists can be avoided.
Algorithm 5 shows the approach taken in this project.
Algorithm Description
The algorithm starts with an empty Ripple Effect puzzle that consists of rooms
of size 1. The first step is to choose a random cell of the puzzle as a starting
13
3 Implementation
Algorithm 5 Generate rooms for a puzzle
Require: empty Ripple Effect puzzle P with rooms of size 1
Require: maximum allowed room size: roomSizeLimit > 2
1: choose a cell cx,y of P
2: cx,y = ’+’
3: progress = false
4: finished = false
5: while finished = false do
6:
while ∃cx,y in P | cx,y = ’+’ do
7:
if possible(x,y,1) then
8:
cx,y = 1
9:
assign ’+’ to all empty neighbours of cx,y
10:
progress = true
11:
else
12:
for z = 2; z ≤ roomSizeLimit AND cx,y = ’+’; z = z + 1 do
13:
if possible(x,y,z) for cx,y merged with a filled neighboring room r
then
14:
merge cx,y and r into one room
15:
cx,y = z
16:
assign ’+’ to all empty neighbours of cx,y
17:
progress = true
18:
end if
19:
end for
20:
if cx,y = ’+’ then
21:
cx,y = ’-’
22:
end if
23:
end if
24:
end while
25:
if progress = true then
26:
for all cx,y in P | cx,y = ’-’ do
27:
cx,y = ’+’
28:
end for
29:
progress = false;
30:
else if ∃cx,y | cx,y = ’-’ then
31:
for all rooms r in P : r neighbour of cx,y do
32:
for all cells cx0 ,y0 in room r do
33:
cx0 ,y0 = ’+’
34:
end for
35:
split room r into rooms of size 1
36:
end for
37:
else
38:
finished = true
39:
end if
40: end while
14
3.5 Puzzle Generator
point and write a ‘+’ into it. The ‘+’ denotes that this cell should be used by
the algorithm in the next step.
The main loop of the algorithm chooses one random cell with a ‘+’ and tries
to add it to the already generated part of the puzzle. This is done by first
trying to enter a 1 into the cell while leaving it as a room of size 1. If that
isn’t possible, it is tried to merge the cell to any of the neighbouring rooms that
belong to the generated part and
If the cell could be added to the generated puzzle, all it’s empty neighbours
are marked with a ‘+’. If the cell could not be added, it is marked with a ‘-’.
This procedure gets repeated until no more cells with a ‘+’ remain. If every
cell has a number in it, the generator is finished, else if the generator could add
new cells in its last execution of the main loop, all ‘-’ are replaced with a ‘+’
and the main loop gets executed again to check if these cells can be added to
the puzzle now.
If the algorithm couldn’t add new cells to the generated puzzle, it starts
backtracking by choosing one of the unassignable cells with a ‘-’, resetting all
of its neighbouring rooms to their initial state and assigning the cells of these
rooms with a ‘+’. Then the main loop is entered again.
Figure 3.3: The generation of a 5 x 5 room distribution
The generation of a 5 x 5 Ripple Effect puzzle can be seen in Figure 3.3. In
this case it has to backtrack two times before a valid room distribution is found.
Algorithm Properties
The advantages of this algorithm are that it needs no additional space for
its computations and can assign rooms to most cells of the puzzle in close to
linear time, because for each cell only some simple checks against their close
neighbours are necessary. The algorithm is not deterministic and therefore
produces different room distributions for the same puzzle dimensions, which is
the intended behaviour for a puzzle generator.
Disadvantages are it will not terminate if it can’t find a correct room distribution and therefore should only be used with an additional constraint (e.g.
15
3 Implementation
limiting the number of backtracking attempts and reporting failure if the limit
is reached) and the values in the rooms will always follow a certain pattern,
e.g. a 2 will always be the neighbor of a 1 in the same room, the 3 will be a
neighbor of either 1 or 2 etc. This problem is avoided by not using the number
assignment created by this algorithm as the solution to the puzzle but search
for a different solution to the same room distribution in the next step.
3.5.2 Ensure Unique Solution
Algorithm 6 Ensure a unique solution
Require: empty Ripple Effect puzzle P with valid room distribution
Require: SAT solver s
1: s.setupClausesFor(P )
2: oldSolution = s.getSolution()
3: s.addClause(!oldSolution)
4: while s.getSolution() != null do
5:
newSolution = s.getSolution()
6:
choose cx,y where newSolution != oldSolution
7:
cx,y of P = value of newSolution v
8:
s.addClause(cx,y = v)
9:
s.addClause(!newSolution)
10:
oldSolution = newSolution
11: end while
If there exists more than one solution to a puzzle, it isn’t fun to solve it.
Therefore one has to ensure that there are at least as many cells prefilled as
needed to allow only one solution.
This is done by taking the puzzle generated in the previous step, finding two
different solutions for it, comparing the solutions and entering the value of a
cell where the solutions differ into the puzzle as long as additional solutions can
be found.
This repeated search for solutions can be done effectively by using a SAT
solver and the Algorithm 6. First the clauses for the empty puzzle have to be
generated and added to the solver. Then the SAT solver has to find the first
solution. The complement of this solution is added as a new clause to the SAT
solver which reduces the valid solutions to all that differ at least at one place
from this first solution.
The SAT solver is asked again to deliver a solution. If there is a solution,
the algorithm chooses a cell where the new solution differs from the previous,
enters its value into the puzzle and as a new clause for the SAT solver. Now
the previous solution is replaced with the current, and the complement of the
current solution is added as a clause to the SAT solver. This process is repeated
as long as new solutions can be found.
If there are no more solutions, the puzzle has a unique solution.
16
3.5 Puzzle Generator
3.5.3 Set the Maximum Difficulty Level
The difficulty can be set by applying the corresponding solving-strategy:
For “very hard” puzzles nothing needs to be done.
For “hard” puzzles the “What-If”-solver needs to be applied. If it can’t solve
the whole puzzle, assign to any of the empty cells its correct value (according to
the solution) and retry. Repeat until the “What-If”-solver can solve the whole
puzzle.
For “medium” puzzles the Extended Simple solver needs to be applied. If it
can’t solve the whole puzzle, assign to any of the empty cells its correct value
(according to the solution) and repeat.
And finally for the “easy” puzzles the Simple Solver needs to be applied.
Again, if it can’t solve the whole puzzle, assign to any of the empty cells its
correct value (according to the solution) and repeat.
17
4 GUI
To allow the user to see and easily manipulate Ripple Effect puzzles, a graphical
user interface had to be created as part of the project. Because the chosen
programming language for puzzle solver and generator was Java and therefore
operating system independent, the graphical user interface was too written in
Java or more precisely with the graphics library “Swing”.
4.1 Swing
Swing is a graphical library developed by Sun Microsystems and part of the Java
Foundation Classes, a framework of interfaces and libraries that is shipped with
the Java Runtime Environment and therefore available on almost every Java
capable system.
It is built on top of AWT (Abstract Window Toolkit) which allows for OS
independent usage of windows and a variety of other GUI utilities such as buttons, text fields, menus, toolbars etc. An interesting detail is that Swing isn’t
thread-safe which means that the programmer has to ensure that threads accessing GUI elements don’t interfere with each other. Therefore it is adviced
to e.g. never directly draw elements but instead overwrite the “paintComponent()” method and signal to Swing that the component should be redrawn by
calling the method “repaint()”.
4.2 Structure of the GUI
Figure 4.1: The packages of Ripple Effect and their dependencies
18
4.2 Structure of the GUI
The structure of Ripple Effect follows the constraints of the model-viewcontroller pattern (MVC). This means especially that neither the core puzzle
classes nor solver or generator access the GUI directly, which can be seen in
the package dependency graph in Figure [4.1], where neither instantiations nor
calls are made to the GUI packages from solver or core packages.
Figure 4.2: The structure of the main GUI classes
All classes relevant to the GUI are located in the package “gui” and its
subpackages. A detailed view on the main gui classes is shown in Figure 4.2. As
can be seen, the “main()” method, which is the entry point for Java programs,
is located in the class “GuiFrontend”. This class is the main window of Ripple
Effect and derived from the class JFrame, a basic all purpose window of the
Swing framework. It instantiates all other GUI components such as the Toolbar,
Menus and the playfield.
The GUI represents itself to the user as can be seen in Figure 4.3.
4.2.1 Playfield
As can be seen in Figure 4.2, the playfield is represented by two classes: PuzzlePanel and PuzzlePanelCell.
PuzzlePanel represents the Ripple Effect puzzle itself and is responsible for
processing all input from keyboard and mouse that is used to manipulate the
puzzle. Therefore the corresponding event listeners are implemented by the
class. It is derived from the class JPanel, a basic container that is used to
manage and display elements in Swing. The PuzzlePanel contains an array
of “PuzzlePanelCell” objects (one for each cell of the underlying puzzle) and
manages their state. It also keeps the information about the current zoom level
(called puzzleFieldSize).
19
4 GUI
Figure 4.3: The user interface of Ripple Effect
PuzzlePanelCell is derived of the class JComponent, a basic and lightweight
class of the Swing framework. It only contains information about how to display its contents depending on the cell value, if it has the focus, if the cell value
is unchangeable and which borders need to be drawn thick or thin. To allow
the custom drawing of borders in varying thickness the method “paintComponent()” was overwritten.
4.2.2 Menus and Toolbars
To allow easy access to the functionality of Ripple Effect a menu and a toolbar
are provided. Most functionality can be accessed by shortcut key combinations
that are displayed next to the menu entries. Not all menu entries may be
accessible at all times. If a tool is not available the corresponding menu entry
and toolbar button will be greyed out and unclickable.
Although most entries are self-explanatory, a short explaination of them will
be given in the following.
Menu File
The first menu entry provides basic functionality to manage Ripple Effect puzzles (see Figure 4.4).
New Puzzle Displays a dialog that allows to either create an empty puzzle
or let a puzzle be generated with a specific size, difficulty level and maximum
room size.
20
4.2 Structure of the GUI
Figure 4.4: The file and edit menus of Ripple Effect
Open Displays a file selection dialog that allows the user to choose a previously
saved puzzle file and load it into the application.
Save Save the current puzzle. If the puzzle has never been saved before, a
dialog appears that allows the user to specify a file name and location for the
save file.
Save As Displays a dialog that allows the user to specify a file name and
location for a new save file and saves the puzzle to that location.
Quit Exits the application. The user will be asked if he/she really wants to
end the application.
Menu Edit
This menu grants access to tools for modification of a loaded or generated puzzle
(see Figure 4.4).
Merge Combines all selected cells into a new room. Existing entries of rooms
may be removed if they don’t fit into the new room. This tool is only available
if the application is switched into Editor Mode.
Check puzzle Checks if the puzzle is solved correctly, has errors in it, if it can
be solved or has multiple solutions. While the check is performed a dialog will
be visible that allows to abort it.
Simple solver Invokes the Simple solver as described in 3.3.1. While the solver
is running a dialog will be visible that allows to abort it.
21
4 GUI
Extended Simple solver Invokes the Extended Simple solver as described in
3.3.2. While the solver is running a dialog will be visible that allows to abort
it.
What-If solver Invokes the What-If solver as described in 3.3.3. While the
solver is running a dialog will be visible that allows to abort it.
SAT solver Invokes the SAT solver as described in 3.4. While the solver is
running a dialog will be visible that allows to abort it. This solver is the only
one that is accessible from the toolbar and by shortcut, because it is the only
one that will solve any solvable puzzle.
Reset puzzle Removes all user entered numbers from the puzzle and therefore
resets it to its initial state.
Redo If one or more changes to the puzzle have been undone by the Undo
command, they can be redone by this command.
Undo If one or more changes to the puzzle have been made they can be undone
by this command. This only works for changes to entries of the puzzle. If the
user switches to Editor mode, the undo history will be lost.
Figure 4.5: The mode and help menus of Ripple Effect
Menu Mode
This menu holds tools to change the currently used mode of the puzzle (Editor
or Standard mode) and to change the display size of the puzzle (see Figure 4.5).
Editor/Standard Mode Switch to the corresponding mode and therefore make
new or other tools to manipulate the puzzle available. By switching to editor
mode the undo history is deleted and the timer is reset.
Zoom In
Increase the size of the displayed cells by 10 pixels.
Zoom Out Reduce the size of the displayed cells by 10 pixels. The minimum
size is 35 pixels.
22
4.2 Structure of the GUI
Menu Help
This menu allows to get help and information about the program (see Figure
4.5).
Show Help Opens the program manual in a new window of the standard webbrowser of the operating system. This manual can also be found in the folder
named manual in the program directory.
About Displays a dialog with information about the author of the program
and how to contact him.
Toolbar Timer
The toolbar has a special button that displays the elapsed time. The time is
displayed in minutes and seconds and by clicking it, the puzzle and timer can
be paused/resumed.
23
5 Performance Measuring
As there are neither automated Ripple Effect solvers nor Ripple Effect puzzle
generators available to-date, the following numbers can and should be used as
reference for any future implementations of such programs.
The performance test is run on a reference PC with Windows XP, an 1,4
GHz AMD Athlon XP 1600+ Processor and 348 MB RAM. The Java Virtual
Machine is initialized with the command line option “-Xmx128M” to give it
access to 128 MB Ram for its heap memory, which is needed to solve the
biggest puzzles of this test without running out of memory.
5.1 Solver Performance
Due to Java’s self-managed memory and the resulting need for periodical maintenance work (like garbage collection), the time needed for the execution of a
piece of code may vary. To reduce the impact of these interruptions on the
results of the performance test, each test is done ten times and the median of
the results is used as the final result.
In addition, only the time needed from sending the puzzle to the solver to
the return of the solution is measured (without the time needed to graphically
represent the result), because Java Swing repaints the GUI asynchronously and
therefore any amount of time can elapse between queueing the task to redraw
the puzzle and the actual redrawing.
The performance of the SAT solver algorithm is measured against five puzzles
from the book [3] and four self-generated puzzles of bigger dimensions with the
highest difficulty level. The manual solving time is the average time needed by
five volunteers to solve the puzzle by hand.
puzzle
Nikoli 15
Nikoli 35
Nikoli 55
Nikoli 75
Nikoli 95
generated
generated
generated
generated
Table 5.1: Solver Performance
dimensions solving time time per cell
08x08
10 ms
0.156 ms
10x10
10 ms
0.100 ms
10x18
10 ms
0.056 ms
10x18
14 ms
0.078 ms
14x24
31 ms
0.092 ms
40x40
200 ms
0.125 ms
60x60
541 ms
0.150 ms
80x80
1127 ms
0.176 ms
99x99
3185 ms
0.325 ms
manual solving time
4 min
11 min
20 min
33 min
56 min
NA min
NA min
NA min
NA min
As can be seen, the solving time for any of the original Nikoli puzzles is
24
5.2 Generator Performance
always less than a second and therefore the used SAT solver seems to perform
very well for all Ripple Effect puzzles targeted at a human audience. The bad
“time per cell” value for the first three entries is the result of the time needed
to instantiate the solver, which is much higher than the actual solving time for
those tiny puzzles.
The “time per cell” value increases with the dimension and therefore the
solving time seems to grow exponentially with the number of cells of the puzzle,
which fits the previously stated NP complexity of solving Ripple Effect puzzles.
5.2 Generator Performance
A performance test for the implemented generator will be omitted, because the
needed time is not only highly dependant on the used parameters like puzzle
dimensions and room size limit, but also variates extremely if the parameters
stay the same.
Even if precise times could be given, the fact that the generator algorithm
may not be able to generate every possible Ripple Effect puzzle and the used
definitions of difficulty may not correspond to those chosen by other software
authors would render the test data useless for objective comparison of future
generator algorithms and implementations.
25
6 Summary
The chosen approach to convert a Ripple Effect puzzle into a satisfiability problem that is solved by a professionally maintained SAT solver has proved itself
to be efficient and easy to implement for any type of puzzle, even if the puzzle
has no or multiple solutions. The implemented graphical user interface allows
also for fast and comfortable manual solving of puzzles and easy creation of
new ones.
Although the implemented generator will find a valid puzzle for most of
the possible parameter combinations such as room size limit and puzzle grid
dimension, it may not be able to generate all possible puzzles and therefore
could be the target of future work. The addition of heuristics for choosing
the most promising backtracking candidates to the generator or the design of
another generation algorithm would help to overcome the limitations of the
current generator (see 3.5.1) and increase the quality of the program.
26
Bibliography
[1] C. Colbourn. The complexity of completing partial latin squares. Discrete
Applied Mathematics 8, 1984.
[2] NIKOLI Co. Ltd. Web nikoli. http://www.nikoli.co.jp/en/.
[3] NIKOLI Co. Ltd. Hakyuu 1. NIKOLI Co. Ltd., 2005.
[4] Sun Microsystems. Java technology. http://java.sun.com.
[5] SAT4J. Sat technology for java. http://www.sat4j.org/.
27
A Proof of NP-Completeness
The simplest way to proof that a problem belongs into NP-complete is to find a
NP-complete problem that can be converted in polynomial or less time into an
instance of this problem and the solution of this problem back into a solution
of the original NP-complete problem.
A Latin square is an n × n table filled with n different symbols in a way
that each symbol occurs exactly once in each row and exactly once in each
column. The problem of filling a partially solved Latin square is proven to be
NP-complete [1]. For simpleness a Latin square with the numbers 1 to n as
symbols is used in this proof.
Figure A.1: Left: Latin square, Right: solved Latin square
One could try to simply convert the Latin square into a Ripple Effect puzzle
by either combining each row (or column) of the square into a room. This
would ensure the usage of each number exactly once per row (or column). But
starting with grids of the dimension 4 × 4 the Ripple Effect rules would allow
solutions that are not valid solutions to the corresponding Latin square, because
the smaller numbers can appear twice in the same column (or row).
By converting a Latin square puzzle of size n × n into a Ripple Effect grid of
size 2n × n, this problem can be prevented.
Each line of the new extended grid gets transformed into a room of size 2n.
Then the second half of every room gets filled with the numbers from 1 to n
in a way that no column contains the same number twice. This can be done in
linear time by using the following formula to determine the value of each cell
(with x and y being 0-based coordinates of the grid):
cx,y = 1 + ((x − n) − y % n)
Now the original Latin square is copied into the first half of the Ripple Effect
grid and each entry is increased by n. This results in a Ripple Effect puzzle that
28
exposes exactly the same behaviour as the Latin square, because all entries in
the second half of the puzzle are bigger than n and therefore each one of them
can only occur once in a column. The lines of the puzzle correspond to rooms
and therefore it is also ensured that no line holds the same number twice. After
the Ripple Effect puzzle is solved, the solution to the Latin square can be
generated from it.
Figure A.2: Top: generated RE puzzle, Bottom: solved RE puzzle
To convert the result of the Ripple Effect puzzle back into a result for the
original Latin square, the first half of the Ripple Effect grid is copied back into
the Latin square and every entry is reduced by n.
29