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).
![]() |
---|
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.
- No row or column has 3-In-A-Row (or 3-In-A-Column) squares of the same color, and
- Each row and column has equal number of blue and white squares.
The given puzzle has this solution:
![]() |
---|
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:
You must write at least one file called
ThreeInARowSolver.kt
. It can contain a class calledThreeInARowSolver
. This class should have the method that performs the backtracking search. The necessary data structures can be kept within this one class, or you may create a separate class forGrid
. You can make theGrid
class disjoint from or nest it insideThreeInARowSolver
. It’s all up to you.Your
main
function is top-level and should reside in the same file as the classThreeInARowSolver
. It reads in the data for the initial grid from standard input, and writes the solution to the standard output.The format of the input is like this. The first line contains an even positive integer
n
. (This means the dimension of the grid isn
byn
.) Then follown
lines, each line containing exactlyn
characters. A position has the characterW
if there is a white square there. It has the characterB
if there is a blue square there. The character-
denotes a blank cell. For example, the grid in Fig 1 is encoded like this6 --W-B- ------ BB--W- -B---- -----W -BW---
The format of the output is like this. It consists of exactly
n
lines, each line of which contains exactlyn
characters. Each character is eitherW
orB
, denoting a white or blue square in that position, respectively. For example, the grid in Fig 2 is encoded like thisBWWBBW WWBWBB BBWBWW WBBWWB BWBWBW WBWBWB
Your final program should be run like this. Let’s say you write only one Kotlin file
ThreeInARowSolver.kt
. It defines theThreeInARowSolver
class and also contains the top-levelmain
function. Further, suppose your data file is named3inarow.in
and contains the input as described in the example above. You should be able to compile and run your program by typing$ kotlinc ThreeInARowSolver.kt $ kotlin ThreeInARowSolverKt < 3inarow.in
Your program should output the 6 output lines described above.
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.