Skip to content

Commit eac5723

Browse files
authored
Merge pull request #2 from timlg07/praktomat-specific-version
Praktomat specific version
2 parents 3eef563 + ef47158 commit eac5723

20 files changed

+177
-57
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,5 @@ local.properties
8484

8585
# Uncomment this line if you wish to ignore the project description file.
8686
# Typically, this file would be tracked if it contains build/dependency configurations:
87-
#.project
87+
#.project
88+
countLines.cmd

Sudoku-Solver/src/de/tim_greller/sudoku/io/Shell.java renamed to Sudoku-Solver/src/sudoku/io/Shell.java

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
package de.tim_greller.sudoku.io;
1+
package sudoku.io;
22

33
import java.io.BufferedReader;
44
import java.io.File;
55
import java.io.IOException;
66
import java.io.InputStreamReader;
7-
import java.util.Collections;
87
import java.util.List;
98
import java.util.stream.Collectors;
109

11-
import de.tim_greller.sudoku.model.Board;
12-
import de.tim_greller.sudoku.model.EnforcedCell;
13-
import de.tim_greller.sudoku.model.EnforcedNumber;
14-
import de.tim_greller.sudoku.model.InvalidSudokuException;
15-
import de.tim_greller.sudoku.model.SudokuBoardSolver;
16-
import de.tim_greller.sudoku.model.SudokuSolver;
10+
import sudoku.model.Board;
11+
import sudoku.model.EnforcedCell;
12+
import sudoku.model.EnforcedNumber;
13+
import sudoku.model.InvalidSudokuException;
14+
import sudoku.model.SudokuBoardSolver;
15+
import sudoku.model.SudokuSolver;
1716

1817
/**
1918
* The shell class handles the interaction between the user and the data model
@@ -53,11 +52,11 @@ public static void main(String[] args) throws IOException {
5352
}
5453

5554
/**
56-
* Reads the next input line and initiates the execution of it.
57-
* Returns {@code false} if EOF is reached.
58-
* Performs no operation for blank lines.
55+
* Interprets the given line of user input and initiates the execution of
56+
* it. Returns {@code false} if EOF is reached and Performs no operation for
57+
* blank lines.
5958
*
60-
* @param stdin The BufferedReader for the standard input stream.
59+
* @param line The line that should be processed.
6160
* @return whether the program should continue execution or terminate after
6261
* the current line of input is processed.
6362
*/
@@ -99,20 +98,24 @@ private static boolean executeCommand(String[] tokenizedInput) {
9998
break;
10099

101100
case "saturate":
102-
saturateSudoku();
101+
printSaturatedSudoku();
103102
break;
104103

105104
case "first":
106-
solveSudoku();
105+
printSolvedSudoku();
107106
break;
108107

109108
case "all":
110109
printAllSolutions();
111110
break;
112111

112+
case "help":
113+
printHelpText();
114+
break;
115+
113116
case "print":
114117
if (requireLoadedBoard()) {
115-
prettyPrint(currentBoard);
118+
System.out.println(currentBoard.prettyPrint());
116119
}
117120
break;
118121

@@ -126,7 +129,7 @@ private static boolean executeCommand(String[] tokenizedInput) {
126129

127130
return true;
128131
}
129-
132+
130133
/**
131134
* Prints all possible solutions of the currently loaded board with one
132135
* solution per line.
@@ -135,31 +138,47 @@ private static void printAllSolutions() {
135138
if (requireLoadedBoard()) {
136139
List<Board> solutions
137140
= currentSolver.findAllSolutions(currentBoard);
138-
Collections.sort(solutions);
139141

140-
// Join the string representation of all sudokus.
141-
String output = solutions.stream()
142-
.map(Board::toString)
143-
.collect(Collectors.joining("\n"));
144-
145-
System.out.println(output);
142+
if (solutions.size() == 0) {
143+
printError("This board is unsolvable");
144+
} else {
145+
146+
// Sort all sudokus and join their string representation.
147+
String output = solutions.stream()
148+
.sorted()
149+
.map(Board::toString)
150+
.collect(Collectors.joining("\n"));
151+
152+
System.out.println(output);
153+
}
146154
}
147155
}
148156

149-
private static void solveSudoku() {
157+
/**
158+
* Prints the first found solution using pretty print.
159+
*/
160+
private static void printSolvedSudoku() {
150161
if (requireLoadedBoard()) {
151162
Board solvedBoard = currentSolver.findFirstSolution(currentBoard);
152-
prettyPrint(solvedBoard);
163+
prettyPrintSolved(solvedBoard);
153164
}
154165
}
155166

156-
private static void saturateSudoku() {
167+
/**
168+
* Pretty prints the the sudoku after all registered saturator strategies
169+
* were applied.
170+
*/
171+
private static void printSaturatedSudoku() {
157172
if (requireLoadedBoard()) {
158173
Board saturatedBoard = currentSolver.saturate(currentBoard);
159-
prettyPrint(saturatedBoard);
174+
prettyPrintSolved(saturatedBoard);
160175
}
161176
}
162177

178+
/**
179+
* Instantiates a new Solver and registers the {@link EnforcedCell} and
180+
* {@link EnforcedNumber} saturators on it.
181+
*/
163182
private static void setupSolver() {
164183
currentSolver = new SudokuBoardSolver();
165184
currentSolver.addSaturator(new EnforcedCell());
@@ -211,12 +230,57 @@ private static void inputSudoku(String[] tokenizedInput) {
211230
}
212231

213232
/**
214-
* Prints the given {@link Board} as a rectangle.
215-
* @param board The board that should be printed, not null.
233+
* Prints the given {@link Board} as a rectangle. If the board is
234+
* {@code null} an error indicating that the board is unsolvable is printed.
235+
*
236+
* @param board The solved board that should be printed, may be null.
237+
*/
238+
private static void prettyPrintSolved(Board board) {
239+
if (board == null) {
240+
printError("This board is unsolvable");
241+
} else {
242+
System.out.println(board.prettyPrint());
243+
}
244+
}
245+
246+
/**
247+
* Prints the help text containing informations about the existing commands
248+
* and their syntax.
216249
*/
217-
private static void prettyPrint(Board board) {
218-
assert (board != null);
219-
System.out.println(board.prettyPrint());
250+
private static void printHelpText() {
251+
System.out.println(
252+
"The sudoku shell is capable of solving every sudoku you "
253+
+ "load. You are not limited to standard 9 by 9 sudokus, but "
254+
+ "can load and solve sudokus of all sizes.\n\n"
255+
+ "Available commands:\n"
256+
257+
+ "input [[<drive>:][<path>]<filename> Loads a sudoku from a"
258+
+ " sudoku file (*.sud) with the given absolute or relative "
259+
+ "path. Paths or filenames with spaces must be put in double "
260+
+ "quotes. The sudoku file has to specify the size of boxes in "
261+
+ "the sudoku, which is done by writing the amount of rows and "
262+
+ "columns in the first line, separated with a space. The "
263+
+ "following lines should contain one row of the sudoku per "
264+
+ "line as a space separated list of its cells. Empty cells are"
265+
+ " indicated as dots.\n"
266+
267+
+ "first Computes and prints the first found solution of the"
268+
+ " sudoku if it is solvable.\n"
269+
270+
+ "all Generates all possible sudokus and prints them "
271+
+ "(one sudoku per line) in ascending order.\n"
272+
273+
+ "saturate Prints the sudoku with all strategies applied if "
274+
+ "they do not lead to an unsolvable sudoku. Since this will "
275+
+ "not do any backtracking, the provided sudoku can, but does "
276+
+ "not have to be fully solved.\n"
277+
278+
+ "print Prints the currently loaded sudoku.\n"
279+
280+
+ "help Shows this help text.\n"
281+
282+
+ "quit Exits the program.\n"
283+
);
220284
}
221285

222286
/**

Sudoku-Solver/src/de/tim_greller/sudoku/io/SudokuFileParser.java renamed to Sudoku-Solver/src/sudoku/io/SudokuFileParser.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
package de.tim_greller.sudoku.io;
1+
package sudoku.io;
22

33
import java.io.BufferedReader;
44
import java.io.File;
55
import java.io.FileReader;
66
import java.io.IOException;
77
import java.util.Optional;
88

9-
import de.tim_greller.sudoku.model.Board;
10-
import de.tim_greller.sudoku.model.InvalidSudokuException;
11-
import de.tim_greller.sudoku.model.Structure;
12-
import de.tim_greller.sudoku.model.SudokuBoard;
9+
import sudoku.model.Board;
10+
import sudoku.model.InvalidSudokuException;
11+
import sudoku.model.Structure;
12+
import sudoku.model.SudokuBoard;
1313

1414
/**
1515
* This class provides the functionality to read a sudoku-file and generate a

Sudoku-Solver/src/de/tim_greller/sudoku/io/package-info.java renamed to Sudoku-Solver/src/sudoku/io/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
* This package provides utility classes for I/O operations on the data model,
33
* such as loading a sudoku from a file and executing operations on it.
44
*/
5-
package de.tim_greller.sudoku.io;
5+
package sudoku.io;

Sudoku-Solver/src/de/tim_greller/sudoku/model/Board.java renamed to Sudoku-Solver/src/sudoku/model/Board.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* An interface for the representation and for solving of Sudokus, which

Sudoku-Solver/src/de/tim_greller/sudoku/model/EnforcedCell.java renamed to Sudoku-Solver/src/sudoku/model/EnforcedCell.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* A solution strategy that sets all cells of a sudoku that can only contain one

Sudoku-Solver/src/de/tim_greller/sudoku/model/EnforcedNumber.java renamed to Sudoku-Solver/src/sudoku/model/EnforcedNumber.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* A solution strategy that sets all cells of a sudoku which have to contain a
@@ -39,16 +39,16 @@ public boolean saturate(Board board) throws UnsolvableSudokuException {
3939
private boolean saturateStructure(Board board, Structure struct, int major)
4040
throws UnsolvableSudokuException {
4141
boolean modifiedBoard = false;
42-
int[] amountsOfpossibleCells = computeAmounts(board, struct, major);
42+
int[] amountsOfPossibleCells = computeAmounts(board, struct, major);
4343

4444
for (int minor = 0; minor < board.getNumbers(); minor++) {
4545
boolean modifiedCurrentCell = false;
4646
int[] possibilities = board.getPossibilities(struct, major, minor);
4747

4848
if (possibilities != null) {
4949
for (int possibility : possibilities) {
50-
if (amountsOfpossibleCells[possibility - 1] == 1) {
51-
50+
51+
if (amountsOfPossibleCells[possibility - 1] == 1) {
5252
if (modifiedCurrentCell) {
5353
/*
5454
* Two values in this structure can only be assigned
@@ -63,7 +63,7 @@ private boolean saturateStructure(Board board, Structure struct, int major)
6363
} catch (InvalidSudokuException e) {
6464
throw new UnsolvableSudokuException();
6565
}
66-
66+
6767
modifiedCurrentCell = true;
6868
modifiedBoard = true;
6969
}

Sudoku-Solver/src/de/tim_greller/sudoku/model/InvalidSudokuException.java renamed to Sudoku-Solver/src/sudoku/model/InvalidSudokuException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* Exception if one likes to set a number which is not possible.

Sudoku-Solver/src/de/tim_greller/sudoku/model/Saturator.java renamed to Sudoku-Solver/src/sudoku/model/Saturator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* An interface which must be implemented by classes which provide a solution

Sudoku-Solver/src/de/tim_greller/sudoku/model/Structure.java renamed to Sudoku-Solver/src/sudoku/model/Structure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* The different types of structures/coordinate systems.

Sudoku-Solver/src/de/tim_greller/sudoku/model/SudokuBoard.java renamed to Sudoku-Solver/src/sudoku/model/SudokuBoard.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
import java.util.BitSet;
44

@@ -42,6 +42,10 @@ public SudokuBoard(int boxRows, int boxCols) {
4242
* <p>Setting a cells content to a number removes this number from the
4343
* possible values in all other cells sharing a structure with the specified
4444
* cell.</p>
45+
* <p>A sudoku is seen as unsolvable if and only if a structure contains a
46+
* duplicate or a cell that can not be set to any number without causing a
47+
* duplicate. It does not check if every structure can contain all numbers.
48+
* </p>
4549
*
4650
* @throws IllegalStateException Trying to overwrite a fixed cell.
4751
*/
@@ -77,7 +81,7 @@ public void setCell(Structure struct, int major, int minor, int number)
7781
}
7882
}
7983
}
80-
84+
8185
/**
8286
* {@inheritDoc}
8387
* Does nothing if the cell is already set to a fixed value.

Sudoku-Solver/src/de/tim_greller/sudoku/model/SudokuBoardSolver.java renamed to Sudoku-Solver/src/sudoku/model/SudokuBoardSolver.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
import java.util.ArrayList;
44
import java.util.Deque;
@@ -68,7 +68,7 @@ private void saturateDirect(Board board) throws UnsolvableSudokuException {
6868
*/
6969
@Override
7070
public Board findFirstSolution(Board board) {
71-
return solve(board, false).get(0);
71+
return solve(board, false).stream().findFirst().orElse(null);
7272
}
7373

7474
/**
@@ -128,12 +128,13 @@ private List<Board> generateCandidates(Board board) {
128128

129129
/**
130130
* Tries to solve a given sudoku using backtracking. The saturators are used
131-
* to speed up the process of sorting out wrong boards.
131+
* to speed up the process of sorting out unsolvable boards.
132132
*
133133
* @param board The sudoku that should be solved. Will not be changed.
134134
* @param requestAllSolutions Whether all solutions are needed or one is
135135
* sufficient.
136136
* @return A List containing one or, if requested, all solutions of board.
137+
* For unsolvable sudokus an empty list is returned.
137138
*/
138139
private List<Board> solve(Board board, boolean requestAllSolutions) {
139140
List<Board> solutions = new LinkedList<Board>();

Sudoku-Solver/src/de/tim_greller/sudoku/model/SudokuSolver.java renamed to Sudoku-Solver/src/sudoku/model/SudokuSolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
import java.util.List;
44

Sudoku-Solver/src/de/tim_greller/sudoku/model/UnsolvableSudokuException.java renamed to Sudoku-Solver/src/sudoku/model/UnsolvableSudokuException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package de.tim_greller.sudoku.model;
1+
package sudoku.model;
22

33
/**
44
* Exception if board gets unsolvable.

Sudoku-Solver/src/de/tim_greller/sudoku/model/package-info.java renamed to Sudoku-Solver/src/sudoku/model/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
* can be used to store and solve sudokus. To enable simple communication with
44
* this model, it contains custom exception- and enumeration-classes.
55
*/
6-
package de.tim_greller.sudoku.model;
6+
package sudoku.model;

Sudoku-Solver/sudokus/impossible.sud

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2 2
2+
. . . .
3+
1 . . .
4+
. 3 . .
5+
. 4 . .

Sudoku-Solver/sudokus/negative.sud

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-1 -1

Sudoku-Solver/sudokus/no.sud

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0 0

Sudoku-Solver/sudokus/smol.sud

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1 1
2+
.

0 commit comments

Comments
 (0)