001 101 110 |
Then you are given some shapes, such as:
|
|
|
Your job is to apply these shapes to the grid, choosing where to apply each shape. When you apply a shape, you will set the values in the grid to the bitwise exclusive or of the grid and the shape. For example, suppose you apply the shape:
1 |
to the upper left cell in the grid. The values in grid will now become:
101 101 110 |
Now, suppose you apply the shape:
01 11 |
to the bottom right corner of the grid. Then the grid becomes:
101 100 101 |
Finally, now suppose you apply the shape:
10 11 10 |
to the right side of the grid. The grid will now become:
111 111 111 |
You are going to do this by writing a recursive program called "shifter." Shifter takes three command line arguments:
shifter row0 row1 row2Row0, row1 and row2 specify the initial configuration of the grid. They are each three-digit binary numbers.
Then, the user enters the shapes on standard input using the following keys:
| A: |
|
|
B: |
|
|
C: |
|
|
D: |
|
|
E: |
|
|||||
| F: |
|
|
G: |
|
|
H: |
|
|
I: |
|
|
J: |
|
|||||
| K: |
|
|
L: |
|
|
M: |
|
|
N: |
|
|
O: |
|
You can enter any number of shapes per line. When standard input is closed, your program should solve the puzzle by finding the correct locations in which to apply each shape so that the final output is all ones. For example:
UNIX> shifter 001 101 110 A E L < CNTL-D > A 0 0 E 1 1 L 0 1 UNIX>This says to apply A at the upper left-hand corner, E shifting the shape one cell to the right and one down, and L shifting one cell to the right.
If there's no solution, your program should print out "No solution."
key rowshift columnshiftIt then prints out the resulting grid. For example:
UNIX> play 001 101 110 001 101 110 A 0 0 Processing Pattern: 100 000 000 Output 101 101 110 E 1 1 Processing Pattern: 000 001 011 Output 101 100 101 L 0 1 Processing Pattern: 010 011 010 Output 111 111 111 < CNTL-D >This lets you test your program. It also lets you generate test files (see below under testing).
Finally, there is also a shell script test_lab.sh that generates nineteen random inputs using random_test and play, and calls shifter to solve the problem. The programs random_test, play and shifter must all be in the current directory.
UNIX> random_test > rtest.txt
UNIX> cat rtest.txt
M 0 0
C 1 2
C 0 1
G 0 0
A 1 1
UNIX> play 111 111 111 < rtest.txt
111
111
111
Processing Pattern:
010
110
010
Output
101
001
101
Processing Pattern:
000
001
001
Output
101
000
100
Processing Pattern:
010
010
000
Output
111
010
100
Processing Pattern:
100
100
100
Output
011
110
000
Processing Pattern:
000
010
000
Output
011
100
000
UNIX> awk '{ print $1 }' rtest.txt
M
C
C
G
A
UNIX> awk '{ print $1 }' rtest.txt | shifter 011 100 000
M 0 0
C 0 1
C 1 2
G 0 0
A 1 1
UNIX> awk '{ print $1 }' rtest.txt | shifter 011 100 000 | play 011 100 000
011
100
000
Enter key rshift cshift
Processing Pattern:
010
110
010
Output
001
010
010
Processing Pattern:
010
010
000
Output
011
000
010
Processing Pattern:
000
001
001
Output
011
001
011
Processing Pattern:
100
100
100
Output
111
101
111
Processing Pattern:
000
010
000
Output
111
111
111
UNIX> sh test_lab.sh
Test 1 111 111 111
Test 2 111 111 111
Test 3 111 111 111
Test 4 111 111 111
Test 5 111 111 111
Test 6 111 111 111
Test 7 111 111 111
Test 8 111 111 111
Test 9 111 111 111
Test 10 111 111 111
Test 11 111 111 111
Test 12 111 111 111
Test 13 111 111 111
Test 14 111 111 111
Test 15 111 111 111
Test 16 111 111 111
Test 17 111 111 111
Test 18 111 111 111
Test 19 111 111 111
UNIX>
typedef struct {
char key;
int row_shifts;
int col_shifts;
char ***patterns;
} Shape;
The key is obvious. Row_shifts is the number of
possible starting rows in which you can apply the pattern, and
col_shifts is the number of possible starting columns
in which you can apply the pattern. Patterns is a
two-dimensional array of pattern strings. For example,
patterns[1][1] contains the string that contains the shape
starting in row 1 and column 1.
Here is an example of the entry for key 'C':
Dllist solve(Dllist input, Dllist ptr, char *grid, Shape *shapes);The first call sets ptr to input->flink. Solve solves the problem recursively, by applying each possible location of the shape specified by ptr, and then recursively calling solve() on the next node of the list (ptr->flink). When you reach the last node on the list, you test the grid to see if it contains all ones. If so, you have success, and you can print out the solution (I do this by returning a dllist -- you can do this however you want). If you don't have a solution, you simply return NULL, and the caller tries its next shape.