enum length ones |
This program should enumerate all strings of length length that contain ones ones, and (length-ones) zeros, and print them on standard output in sorted order. For example:
You may puzzle about how to do this, but it is easy with recursion. What I did was define a class called Enum, which has two public methods:UNIX> enum 2 2 11 UNIX> enum 2 1 01 10 UNIX> enum 2 0 00 UNIX> enum 3 1 001 010 100 UNIX> enum 3 2 011 101 110 UNIX> enum 5 3 00111 01011 01101 01110 10011 10101 10110 11001 11010 11100 UNIX> enum 100 100 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 UNIX> enum 100 0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 UNIX>
do_enumeration() is recursive. The base case is when index is equal to length. Then it prints out the string and returns. In other cases, it calculates whether the character at the given index can be a zero. If so, it sets it to zero and recursively calls do_enumeration() with an incremented index, and the same number-of-ones.
When that recursive call returns, it determines if the character at the given index can be a one. If so, it sets it to one and recursively calls do_enumeration() with an incremented index, and the with number-of-ones decremented by one.
That's all there is to it.
You apply the active shape to a part of the grid where it fits. For example, in the picture above, you can apply the active shape to row zero, row one or row two (life is zero-indexed, of course). When you apply the shape, all grid cells that the shape overlaps change swords to shields and vice versa. For example, suppose you apply the active shape to row zero. The state of the system then changes to:
The next shape can be applied to row 0 or row 1. Suppose we apply it to row 1. Now the state of the system is:
There is one more shape, which can be applied to columns 0, 1 or 2. We apply it do column zero, and the grid becomes all swords:
Those are the mechanics of the game. You are given a grid of swords and shields and a collection of shapes. Your goal is to apply all of the shapes to the grid so that you end up with a grid of all swords.
Here's a second example:
There are nine places for that first shape to go. Since I know the solution, I know it gets applied at row 1, column 1:
There are four places for the next shape -- we apply it to row 0, column 1:
I think you can figure out where that last shape goes.
Thus, the grid in our first example is:
{ "100", "101", "000" } |
and the grid in the second example is:
{ "100", "101", "001" } |
We can also represent shapes as grids of zeros and ones. For example, the shapes in the first example are:
{ "111" } { "110", "011" } { "1", "1", "1" } |
and the shapes in the second example are:
{ "1" } { "11", "10" } { "01", "11" } |
I have written an interactive game player, called ss_player, which takes a prompt and then a grid as command line arguments. After the prompt, each word on the command line specifies a different row of the grid. These words must all be the same size, and they must be composed solely of zeros and ones. Suppose I want to play using the first example above. Then I can play with:
UNIX> ss_player ShapeShifter: 100 101 000 The Grid: 100 101 000 ShapeShifter:At the prompt, I enter a shape and where to apply it. Each row of the shape is a separate word, and the last two words must specify a row and a column. Below, I show how you would specify the solution to the first example:
UNIX> ss_player ShapeShifter: 100 101 000 The Grid: 100 101 000 ShapeShifter: 111 0 0 The Grid: 011 101 000 ShapeShifter: 110 011 1 0 The Grid: 011 011 011 ShapeShifter: 1 1 1 0 0 The Grid: 111 111 111 ShapeShifter: <CNTL-D> UNIX>Go ahead and try to do the second example on your own.
If you give a prompt of "-", there will be no prompt, which is useful for when you use the player with a file or output of a program as input.
For example, the file ex1.txt contains the shapes for the first example:
111 110 011 1 1 1 |
ex2.txt contains the shapes for the second example. Here's the program running the two examples:
UNIX> ss_solver 100 101 000 < ex1.txt 111 0 0 110 011 1 0 1 1 1 0 0 UNIX> ss_solver 100 101 001 < ex2.txt 1 1 1 11 10 0 1 01 11 1 0 UNIX>In the first example, shape "111" was applied at grid coordinates (0,0), then shape "110 011" was applied at grid coordinates (1,0), and finally the shape "1 1 1" was applied at grid coordinates (0,0). Note that shapes are printed out in the same format in which they were read from standard input and that the shapes are being printed in the same order as they were read from standard input.
Here are two examples. The first creates a 3x4 grid that is solvable with the given pieces. The second creates a 4x4 grid whose solvability is unknown. The program sed is used to strip out the first two lines of standard input.
UNIX> ss_random_game usage: ss_random_game rows cols nshapes solvable(y|u) UNIX> ss_random_game 3 4 4 y > tmp-test1.txt UNIX> cat tmp-test1.txt Grid: 0010 1111 1101 Shapes: 1 1 1111 1110 11 1 UNIX> sed 1,2d tmp-test1.txt 1 1 1111 1110 11 1 UNIX> sed 1,2d tmp-test1.txt | ss_solver 0010 1111 1101 1 1 0 2 1111 1110 0 0 11 1 0 1 2 2 UNIX> sed 1,2d tmp-test1.txt | ss_solver 0010 1111 1101 | ss_player - 0010 1111 1101 The Grid: 0010 1111 1101 The Grid: 0000 1101 1101 The Grid: 1111 0011 1101 The Grid: 1111 1111 1101 The Grid: 1111 1111 1111 UNIX> ss_random_game 4 4 4 u > tmp-test2.txt UNIX> cat tmp-test2.txt Grid: 1100 1101 0001 1110 Shapes: 101 0111 0010 1110 11 010 111 111 001 UNIX> sed 1,2d tmp-test1.txt | ss_solver 1100 1101 0001 1110 UNIX>Since there is no output from ss_solver, the puzzle is not solvable.
When it is done running, there will be four new files:
Here's an example -- I set the environment variable l so that I can use the programs in the lab directory, and I don't have to type so much:
UNIX> $l/ss_random_game 4 4 4 y > tmp-test.txt UNIX> cat tmp-test.txt Grid: 0110 1010 1110 0100 Shapes: 11 1001 111 010 101 10 11 10 UNIX> sh $l/ss_tester.sh usage: sh ss_tester.sh your-solver my-solver player output-of-ss_random_game UNIX> sh $l/ss_tester.sh ss_solver $l/ss_solver $l/ss_player tmp-test.txt Correct UNIX> cat tmp-pieces.txt 11 1001 111 010 101 10 11 10 UNIX> cat tmp-yourpieces.txt 11 1001 111 010 101 10 11 10 UNIX> cat tmp-youroutput.txt 11 3 0 1001 0 0 111 010 101 1 1 10 11 10 1 2 UNIX> cat tmp-yourgame.txt The Grid: 0110 1010 1110 0100 The Grid: 0110 1010 1110 1000 The Grid: 1111 1010 1110 1000 The Grid: 1111 1101 1100 1101 The Grid: 1111 1111 1111 1111 UNIX>Here are two more examples. In the first, I have a program called badsolver1, which doesn't solve the problem:
UNIX> sh $l/ss_tester.sh badsolver1 $l/ss_solver $l/ss_player tmp-test.txt Incorrect -- your solution does not solve the puzzle correctly. UNIX> cat tmp-youroutput.txt 11 0 0 1001 0 0 111 010 101 0 0 10 11 10 0 0 UNIX> cat tmp-yourgame.txt The Grid: 0110 1010 1110 0100 The Grid: 1010 1010 1110 0100 The Grid: 0011 1010 1110 0100 The Grid: 1101 1110 0100 0100 The Grid: 0101 0010 1100 0100 UNIX>The second program badsolver2 solves the puzzle, but doesn't use the right pieces:
UNIX> sh $l/ss_tester.sh badsolver2 $l/ss_solver $l/ss_player tmp-test.txt Incorrect -- your solution does not use the correct pieces in the correct order. UNIX> cat tmp-youroutput.txt 1010 0111 0000 0001 0 0 0010 0000 0010 1010 0 0 0100 0010 0010 0000 0 0 0101 0000 0001 0000 0 0 UNIX>If the tester fails, try to figure out why with the output files, and with my correct solver.
If index is less than the number of shapes, then you are going to apply the shape at every potential position, and after each application, you call the method recursively on the next index. If that call fails, then you call Apply() again to undo the first Apply(), and then you try the next potential position.
There are obviously other ways to structure this program, but that seemed easiest to me.