3-In-A-Row Solver

Start: 12/6/2018
Due: 12/14/2018, by the beginning of class
Collaboration: individual or pair programming
Important Links: style guidelines, maze.zip, nQueens.zip, gradesheet

Lab idea from Dave Reed, Creighton University.


In the 3-In-A-Row puzzle you are given an n by n grid for some even integer n. The grid is partially filled—some cells are occupied by blue squares, and some by white squares. The rest of the grid is empty (shown as gray).

Starting grid
Figure 1. Starting grid

You have to fill the grid with blue and white squares in such a way that the following two conditions are satisfied.

  1. No row or column has 3-In-A-Row (or 3-In-A-Column) squares of the same color, and
  2. Each row and column has equal number of blue and white squares.

The given puzzle has this solution:

Solution grid
Figure 2. Solution grid

A human trying to solve this puzzle will have to carefully reason her way through it using logical analysis. See an example of such analysis at 3-In-A-Row help. Nevertheless, we can write a computer program that takes an initial grid configuration and searches for an answer. However, because of the exponential growth rate in the size of the search space, a naive brute-force search will take prohibitively long. We need to search intelligently.

Backtracking

Backtracking is an established search method for solving many intractable computational problems, including a problem like the 3-In-A-Row puzzle. The algorithm starts with an empty current partial solution. It keeps attempting to complete the current partial solution to a full solution by incrementally adding to the current partial solution one new item at each step. It will systematically try all possibilities of expanding the current partial solution, so long as it cannot prove that the current partial solution is doomed, i.e., not capable of being expanded to a complete solution. Immediately after trial adding a new item to the current partial solution, it checks whether this results in a full solution or not. If it does, the algorithm halts and declares success. Otherwise, it checks whether the last addition has resulted in a doomed partial solution or not. If the new partial solution is not doomed, it continues the search using the new partial solution as the current partial solution. If the new partial solution is doomed, it retracts the last addition and continues with the next possible way to expand this current partial solution. If all possible ways to expand the current partial solution has been exhausted without finding a solution, it retracts its last addition, and continues the search. The search stops when it is not possible to expand the current partial solution, and the current partial solution is empty. In such a case, it declares failure.

This basic algorithm can be modified to search for all solutions instead of just one solution.

Getting Started

First, make sure you understand the rules and objectives of the puzzle. Second, study the lecture notes on backtracking. Third, design your backtracking search algorithm for the puzzle. Decide on the data structures to be used, the ordering of the items to be added to the current partial solution, how to check for success condition, how to check whether a partial solution is doomed or not, etc. Fourth, write pseudocode for the search. Last, you can now implement your pseudocode as a Kotlin program. Don’t forget to test as soon as you have written even one function.

Required Structure

Instead of being given a skeleton Kotlin file to work from, you are going to create the code more or less from scratch. However, in order to enforce some uniformity (which will make the grading easier), we request that you do certain things:

Extra Credit

You must have completed the program for the regular part described above before attempting this extra credit part. Your attempted extension to the basic program will not be graded unless you also submit a correct program for the regular part. You can make either one or both of the following extensions.

The first entension is to change the output of your program. This will make it easy for the player to check the correctness of the program’s output. Instead of just simple text, make it display graphically the input grid along side the solution grid. You can display the grids using SVG tags in an html file like we did in the Mondrian Art recursive graphics project, or use Sedgewick’s StdDraw library, or Java Swing library. It’s all up to you.

Here is my program and the input file described above. Save these two files (say in ~/Downloads directory) and execute these commands

$ cd ~/Downloads
$ java -jar ThreeInARowSolverExtendedKt.jar < 3inarow.in > 3inarow.html
$ open 3inarow.html

on a Macintosh machine in the lab to see how the program works.

The second extension is to animate the backtracking search in a similar fashion to this one

for the 8-queen problem. (Gif file from wikipedia on Eight queens puzzle.)

Submission

As usual, you should submit via Moodle. Submit the ThreeInARowSolver.kt file if you are attempting the basic backtracking algorithm only. Submit both ThreeInARowSolver.kt and ThreeInARowSolverExtended.kt in a zip archive if you also attempt the first extra credit extension. Submit ThreeInARowSolver.kt, ThreeInARowSolverExtended1.kt, and ThreeInARowSolverExtended2.kt, in a zip archive if you attempt both extra credit extensions.