C89, 436 characters
Original source (75 lines, 1074 characters):
#include
#include
int board[9][9];
int zeroes[9];
char presses[99];
int size;
int i;
#define TOGGLE { \
board[i][j] ^= 4; \
if(i > 0) \
board[i-1][j] ^= 4; \
if(j > 0) \
board[i][j-1] ^= 4; \
board[i+1][j] ^= 4; \
board[i][j+1] ^= 4; \
presses[i*size + i + j] ^= 118; /* '.' xor 'X' */ \
}
void search(int j)
{
int i = 0;
if(j == size)
{
for(i = 1; i < size; i++)
{
for(j = 0; j < size; j++)
{
if(board[i-1][j])
TOGGLE
}
}
if(memcmp(board[size - 1], zeroes, size * sizeof(int)) == 0)
puts(presses);
for(i = 1; i < size; i++)
{
for(j = 0; j < size; j++)
{
if(presses[i*size + i + j] & 16)
TOGGLE
}
}
}
else
{
search(j+1);
TOGGLE
search(j+1);
TOGGLE
}
}
int main(int c, char **v)
{
while((c = getchar()) != EOF)
{
if(c == '\n')
{
size++;
i = 0;
}
else
board[size][i++] = ~c & 4; // '.' ==> 0, '*' ==> 4
}
memset(presses, '.', 99);
for(c = 1; c <= size; c++)
presses[c * size + c - 1] = '\n';
presses[size * size + size] = '\0';
search(0);
}
Compressed source, with line breaks added for your sanity:
#define T{b[i][j]^=4;if(i)b[i-1][j]^=4;if(j)b[i][j-1]^=4;b[i+1][j]^=4;b[i][j+1]^=4;p[i*s+i+j]^=118;}
b[9][9],z[9],s,i;char p[99];
S(j){int i=0;if(j-s){S(j+1);T S(j+1);T}else{
for(i=1;i
Note that this solution assumes 4-byte integers; if integers are not 4 bytes on your system, replace the 4 in the call to memcmp
with your integer size. The maximum sized grid this supports is 8x8 (not 9x9, since the bit flipping ignores two of the edge cases); to support up to 98x98, add another 9 to the array sizes in the declarations of b
, z
and p
and the call to memset
.
Also note that this finds and prints ALL solutions, not just the first solution. Runtime is O(2^N * N^2), where N is the size of the grid. The input format must be perfectly valid, as no error checking is performed -- it must consist of only .
, *
, and '\n'
, and it must have exactly N lines (i.e. the last character must be a '\n'
).