M README => README +1 -0
@@ 71,6 71,7 @@ XY [r] - Reveal cell XY.
XY t N - Test if cell XY has value N
n [N] - Show 1 or N next hints.
p - Print the board.
+P - Pretty print the board.
s - Show a table with all coordinates.
e - Open the board in $EDITOR (to add values to the partial solution).
h - Show this help text.
M ksudhints.6 => ksudhints.6 +9 -0
@@ 3,6 3,9 @@
ksudhints \- Get hints on a solved sudoku puzzle
.SH SYNOPSIS
.B ksudhints
+[
+.B -P
+]
.BI \-s
.I file
.BI \-p
@@ 17,6 20,9 @@ starting in the top left corner.
It also let's you fill in already solved cells while ignoring wrong input.
.SH OPTIONS
.TP
+.B -P
+pretty print by default
+.TP
.B -s
a solution as given by ksudbf
.TP
@@ 41,6 47,9 @@ Test if cell XY has value N
.B n [N]
Show 1 or N next hints
.TP
+.B P
+Pretty print the board
+.TP
.B p
Print the board
.TP
M ksudhints.c => ksudhints.c +85 -7
@@ 49,11 49,13 @@ static struct cell *next_cell(void);
static int parse_grid(FILE *file);
static void parse_solution(FILE *file);
static void parse_user_input(FILE *file);
+static void pretty(void);
static void print(FILE *file);
static struct cell *random_cell(void);
static struct cell *xy2cell(int n);
/* Globals */
+int opt_pretty;
int solution[9][9];
size_t cage_cnt;
struct cage cages[MAX_CAGES * sizeof(struct cage)];
@@ 80,6 82,9 @@ help(void)
"p",
"Print the board.");
printf("%-10s - %s\n",
+ "P",
+ "Pretty print the board.");
+ printf("%-10s - %s\n",
"s",
"Show a table with all coordinates.");
printf("%-10s - %s\n",
@@ 313,11 318,70 @@ invalid_input:
exit(1);
}
+/*
+ * Pretty print the board with cage boundaries.
+ *
+ * The idea for this was stolen from
+ * https://github.com/Barium/killer-sudoku-solver.git
+ * by Tommy Andersen <andersentommy@gmail.com>.
+ */
+void
+pretty(void)
+{
+ char *vs, vsep[sizeof("|---+---+---+---+---+---+---+---+---+")];
+ int v;
+
+ puts("|---+---+---+---+---+---+---+---+---+");
+
+ for (int i = 0; i < 9; i++) {
+ vs = vsep;
+ *vs++ = '|';
+ *vs = '\0';
+ fputc('|', stdout);
+ for (int j = 0; j < 8; j++) {
+ v = cells[i][j].value;
+ printf(" %c ", v ? (char)(v + '0') : '.');
+ if (cells[i][j].cage == cells[i][j + 1].cage)
+ fputc(' ', stdout);
+ else
+ fputc('|', stdout);
+
+ if (i < 8 && cells[i][j].cage == cells[i + 1][j].cage)
+ strcat(vs, " ");
+ else
+ strcat(vs, "---");
+ vs += 3;
+ *vs++ = '+';
+ *vs = '\0';
+ }
+ v = cells[i][8].value;
+ if (i < 8 && cells[i][8].cage == cells[i + 1][8].cage)
+ strcat(vs, " ");
+ else
+ strcat(vs, "---");
+ vs += 3;
+ *vs++ = '|';
+ *vs = '\0';
+ printf(" %c ", v ? (char)(v + '0') : '.');
+ fputc('|', stdout);
+ fputc('\n', stdout);
+ if (i < 8)
+ puts(vsep);
+ }
+
+ puts("|---+---+---+---+---+---+---+---+---+");
+}
+
void
print(FILE *file)
{
int v;
+ if (file == stdout && opt_pretty) {
+ pretty();
+ return;
+ }
+
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 8; j++) {
v = cells[i][j].value;
@@ 381,20 445,28 @@ main(int argc, char *argv[])
struct cell *cell;
struct cell *revealed[82];
- if (argc != 5)
+ if (argc < 5)
goto usage_err;
for (int i = 1; i < argc; i++) {
- opt = argv[i++];
- if (*opt != '-' || !*++opt || i == argc)
+ opt = argv[i];
+ if (*opt != '-' || !*++opt)
goto usage_err;
switch (*opt) {
+ case 'P':
+ opt_pretty = 1;
+ continue;
+ }
+
+ if (i == argc - 1) goto usage_err;
+
+ switch (*opt) {
case 's':
- solution_file = argv[i];
+ solution_file = argv[++i];
break;
case 'p':
- grid_file = argv[i];
+ grid_file = argv[++i];
break;
default:
goto usage_err;
@@ 499,6 571,9 @@ main(int argc, char *argv[])
}
switch (cmd) {
+ case 'P':
+ pretty();
+ break;
case 'e':
if (!(editor = getenv("EDITOR"))) {
fputs("EDITOR not set!", stderr);
@@ 539,7 614,10 @@ main(int argc, char *argv[])
}
revealed[idx] = cell;
}
- print(stdout);
+ if (opt_pretty)
+ pretty();
+ else
+ print(stdout);
if (count == 82)
break;
for (int i = 0; i < idx; i++) {
@@ 612,6 690,6 @@ main(int argc, char *argv[])
return 0;
usage_err:
- fputs("USAGE: ksudhints -p FILE -s FILE\n", stderr);
+ fputs("USAGE: ksudhints [-P] -p FILE -s FILE\n", stderr);
return 1;
}
M t/0006 => t/0006 +1 -0
@@ 16,6 16,7 @@ XY [r] - Reveal cell XY.
XY t N - Test if cell XY has value N
n [N] - Show 1 or N next hints.
p - Print the board.
+P - Pretty print the board.
s - Show a table with all coordinates.
e - Open the board in $EDITOR (to add values to the partial solution).
h - Show this help text.
A t/0007 => t/0007 +50 -0
@@ 0,0 1,50 @@
+#!/bin/sh
+set -e
+
+# Use ksudhints to pretty print the solution of the example
+
+dir="/tmp/$$"
+out="${dir}/out"
+expected="${dir}/expected"
+
+mkdir $dir || exit 2
+
+cat > "$expected" << 'EOF'
+Commands:
+XY [r] - Reveal cell XY.
+[XY] r [N] - Reveal 1 or N random cells starting with cell XY.
+XY t N - Test if cell XY has value N
+n [N] - Show 1 or N next hints.
+p - Print the board.
+P - Pretty print the board.
+s - Show a table with all coordinates.
+e - Open the board in $EDITOR (to add values to the partial solution).
+h - Show this help text.
+
+Press <Enter> without command to repeat the previous N commands.
+Press ^D to see the complete solution and exit.
+|---+---+---+---+---+---+---+---+---+
+| 2 1 | 5 6 4 | 7 | 3 | 9 | 8 |
+|---+---+---+---+---+ + + + |
+| 3 6 | 8 9 | 5 2 | 1 | 7 | 4 |
+| + +---+---+ +---+---+---+ |
+| 7 9 | 4 3 | 8 | 1 | 6 5 | 2 |
+|---+---+---+ +---+ + +---+ |
+| 5 | 8 6 | 2 | 7 | 4 | 9 | 3 | 1 |
+| +---+---+---+ + +---+ +---|
+| 1 | 4 2 | 5 | 9 | 3 | 8 6 | 7 |
+|---+ +---+ + +---+---+---+ |
+| 9 | 7 | 3 | 8 | 1 | 6 | 4 2 | 5 |
+| +---+ + +---+ +---+---+---|
+| 8 | 2 1 | 7 | 3 | 9 5 | 4 6 |
+| +---+---+---+ +---+---+ + |
+| 6 | 5 | 9 | 4 2 | 8 7 | 1 3 |
+| + + + +---+---+---+---+---|
+| 4 | 3 | 7 | 1 | 6 5 2 | 8 9 |
+|---+---+---+---+---+---+---+---+---+
+EOF
+
+: | ./ksudhints -P -p example/input -s example/solution > "$out"
+diff -u "$out" "$expected" || { echo /tmp/$$; exit 1; }
+
+rm -r $dir