~rkta/ksudbf

96595c487f98c76282b2e2b4f0f2b31fa8e81de8 — Rene Kita 1 year, 5 months ago d6df729 master
Add pretty print command

Thanks to Tommy Andersen <andersentommy@gmail.com> for the idea!

See https://github.com/Barium/killer-sudoku-solver.git
5 files changed, 146 insertions(+), 7 deletions(-)

M README
M ksudhints.6
M ksudhints.c
M t/0006
A t/0007
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