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
© Copyright 2026 Paperzz