Last active
August 29, 2015 14:14
-
-
Save markjgap/c799a720a5facf986fd6 to your computer and use it in GitHub Desktop.
Java program solves a Sudoku puzzle. It is able to target empty squares, search for all possible answers and apply an algorithm to determine the correct solution to complete the puzzle.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Java program used to solve a Sudoku puzzle. It is able to target empty squares, search for all possible answers | |
* and apply an algorithm to determine the correct solution to complete the puzzle. | |
*/ | |
import java.util.*; | |
import java.io.*; | |
public class Sudoku { | |
public static void main (String[] args) { | |
// verifies if text file included in command line. | |
if (args.length < 1) { | |
System.out.println("Missing Sudoku File!"); | |
System.out.println("Usage: java Sudoku <filename_1>.txt <filename_2>.txt ... <filename_n>.txt"); | |
return; | |
} | |
for(int len = 0; len<args.length; len++){ | |
List<Integer> boardInitVal = new ArrayList<Integer>(); | |
int board[][] = new int[9][9]; // initialize board size | |
String fileName = new String(args[len]); | |
System.out.println("======================="); | |
System.out.println(fileName + "\n"); | |
try { // try to load in external text file | |
File file = new File(fileName); | |
Scanner fileScanner = new Scanner(file); | |
while (fileScanner.hasNextInt()){ | |
int num = fileScanner.nextInt(); | |
boardInitVal.add(num); | |
} | |
fileScanner.close(); | |
} | |
catch (FileNotFoundException e){ | |
System.out.println("File " + fileName + " not found!"); | |
e.printStackTrace(); | |
} | |
// loops through and sets initial values to board | |
int index = 0; | |
for (int i=0; i<9; i++){ | |
for (int j=0; j<9; j++){ | |
board[i][j] = boardInitVal.get(index); | |
index++; | |
} | |
} | |
printBoard(board); //print board before solution | |
int runAgain = 0; | |
do{ | |
runAgain = 0; | |
for (int i=0; i<9; i++){ | |
for (int j=0; j<9; j++){ | |
if (board[i][j] == 0){ | |
List<Integer> numRange = Arrays.asList(1,2,3,4,5,6,7,8,9); | |
Set<Integer> range = new HashSet<Integer>(); | |
Set<Integer> h = new HashSet<Integer>(); | |
Set<Integer> v = new HashSet<Integer>(); | |
Set<Integer> s = new HashSet<Integer>(); | |
h = searchHorizontal(i,j, board); // returns all used integers in horizontal row | |
v = searchVertical(i,j, board); // returns all used integers in vertical row | |
s = searchSection(i,j, board); // returns all used integers in 3x3 section | |
h.addAll(v); // combines horizontal with vertical | |
h.addAll(s); // combines horizonal/vertical with 3x3 section | |
range.addAll(numRange); // list of 1-9 integers to compare with taken integers | |
range.removeAll(h); // finds all possible solutions | |
if(range.size()==1){ // if empty square has only 1 solution in range | |
board[i][j] = range.hashCode(); // fill it with that solution | |
runAgain = 1; | |
} | |
} | |
} | |
} | |
} while(runAgain==1); // Can not find solution using "easy" method algorithm | |
int solved = isSolved(board); | |
if(solved == 0){ | |
System.out.println("Can not solve " + fileName); | |
System.out.println("Not an \"Easy\" Sudoku Puzzle"); | |
System.out.println("======================="); | |
continue; | |
} | |
// if board has solution, prints solved board | |
else { | |
System.out.println("Solution to " + fileName + "\n"); | |
printBoard(board); | |
System.out.println("======================="); | |
// writes solution to text file | |
try { | |
String outputFile = fileName.split("[.]")[0]; | |
outputFile += "_sol.txt"; | |
PrintWriter writer = new PrintWriter(outputFile); | |
for(int i = 0; i<9; i++){ | |
for(int j = 0; j<9; j++){ | |
writer.print(board[i][j]+ " "); | |
} | |
writer.println(); | |
} | |
writer.close(); | |
} | |
catch (IOException e){ | |
System.out.println("Error: Could not saved a solutions file"); | |
e.printStackTrace(); | |
return; | |
} | |
} | |
} | |
} | |
////////// methods ////////// | |
/* | |
* Checks to see if board has been completely solved. If there are any 0's | |
* thenboard is unsolved. 0's are meant as an empty square. | |
* @param board - a 2D array that represents a 9x9 sudoku board | |
* @return - 0 if unsolved board. 1 if solved board. | |
*/ | |
public static int isSolved(int[][] board){ | |
for(int i=0; i<9; i++){ | |
for(int j=0; j<9; j++){ | |
if(board[i][j] == 0){ | |
return 0; | |
} | |
} | |
} | |
return 1; | |
} | |
/* | |
* Prints the sudoku board | |
* @param board - a 2D array that represents a 9x9 sudoku board | |
*/ | |
public static void printBoard(int[][] board){ | |
int horLine = 0; | |
int vertLine = 1; | |
for (int i=0; i<9; i++){ | |
if(horLine%3==0 && horLine%9!=0){ | |
System.out.println("----------------------"); | |
} | |
horLine++; | |
for (int j=0; j<9; j++){ | |
System.out.print(board[i][j] + " "); | |
if(vertLine%3==0 && vertLine%9!=0){ | |
System.out.print("| "); | |
} | |
vertLine++; | |
} | |
System.out.println(); | |
} | |
System.out.println(); | |
} | |
/* | |
* Gathers all integers from a particular row | |
* @param x - the x cooridinate of an empty square | |
* @param y - the y cooridinate of an empty square | |
* @param board - a 2D array that represents a 9x9 sudoku board | |
* @return - a set of integers from a particular row | |
*/ | |
public static Set<Integer> searchHorizontal(int x, int y, int[][] board){ | |
Set<Integer> horizontalSet = new HashSet<Integer>(); | |
for(int j = 0; j<9; j++){ | |
horizontalSet.add(board[x][j]); | |
} | |
return horizontalSet; | |
} | |
/* | |
* Gathers all integers from a particular column | |
* @param x - the x cooridinate of an empty square | |
* @param y - the y cooridinate of an empty square | |
* @param board - a 2D array that represents a 9x9 sudoku board | |
* @return - a set of integers from a particular column | |
*/ | |
public static Set<Integer> searchVertical(int x, int y, int[][] board){ | |
Set<Integer> verticalSet = new HashSet<Integer>(); | |
for(int i = 0; i<9; i++){ | |
verticalSet.add(board[i][y]); | |
} | |
return verticalSet; | |
} | |
/* | |
* Gathers all integers from a particular 3x3 section | |
* @param x - the x cooridinate of an empty square | |
* @param y - the y cooridinate of an empty squarde | |
* @param board - a 2D array that represents a 9x9 sudoku board | |
* @return - a set of integers from a particular section | |
*/ | |
public static Set<Integer> searchSection(int i, int j, int[][] board){ | |
Set<Integer> sectionSet = new HashSet<Integer>(); | |
int xPos = i < 3 ? 0 : i < 6 ? 3 : 6; // finds the x position of the first square of a section | |
int yPos = j < 3 ? 0 : j < 6 ? 3 : 6; // finds the y position of the first square of a section | |
for(int x1 = xPos; x1 < xPos+3; x1++){ | |
for(int y1 = yPos; y1 < yPos+3; y1++){ | |
sectionSet.add(board[x1][y1]); | |
} | |
} | |
return sectionSet; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment