UNIX> g++ -Wall -Wextra -std=c++11 -o matrix_enum matrix_enum.cpp
Part of this research was performing enumerations of square matrices. The elements in the matrices can be any of three characters: '.', 'X' and 'E'. The enumeration is parameterized by two values:
XE. .X. ..X |
X.E .X. ..X |
X.. EX. ..X |
X.. .XE ..X |
X.. .X. E.X |
X.. .X. .EX |
XE. ..X .X. |
X.E ..X .X. |
X.. E.X .X. |
X.. .EX .X. |
X.. ..X EX. |
X.. ..X .XE |
EX. X.. ..X |
.XE X.. ..X |
.X. XE. ..X |
.X. X.E ..X |
.X. X.. E.X |
.X. X.. .EX |
EX. ..X X.. |
.XE ..X X.. |
.X. E.X X.. |
.X. .EX X.. |
.X. ..X XE. |
.X. ..X X.E |
E.X .X. X.. |
.EX .X. X.. |
..X EX. X.. |
..X .XE X.. |
..X .X. XE. |
..X .X. X.E |
E.X X.. .X. |
.EX X.. .X. |
..X XE. .X. |
..X X.E .X. |
..X X.. EX. |
..X X.. .XE |
Your job is to write a program called matrix_enum, which takes three command line arguments: W, E and either an 'x' or an 'h'. Your program will enumerate all of the matrices for W and E, in any order you want, and print them out in one of the following two formats:
UNIX> matrix_enum 2 0 x X. .X .X X. UNIX> |
UNIX> matrix_enum 2 1 x XE .X X. EX EX X. .X XE UNIX> |
UNIX> matrix_enum 2 2 x XE EX EX XE UNIX> |
UNIX> matrix_enum 2 0 h 1 2 2 1 UNIX> |
UNIX> matrix_enum 2 1 h 3 2 1 3 3 1 2 3 UNIX> |
UNIX> matrix_enum 2 2 h 3 3 3 3 UNIX> |
.X. ..X X..I don't want you to use next_permutation() to implement this part. Use the recursive technique specified in the Enumeration lecture notes, in the section entitled "Using Recursion to Permute." If you use next_permutation(), you will lose 10 points on this lab, so when you're developing your code, you may want to start by using next_permutation(), and then changing it to use recursion when you've gotten everything else working.
At the second level, you have W2-W potential locations for the 'E' characters. Thus, this is an "n choose k" where n is equal to W2-W and k is equal to E. Implement this using the recursive technique specified in the Enumeration lecture notes, in the section entitled "Using Recursion to Perform an "n choose k" Enumeration."
When I did this, I created a vector out of the non-'X' matrix elements. I stored these as numbers: (row * W + column). I then enumerated all ways to choose E of these, using the same technique as in the lecture notes. Continuing the example above, suppose W equals three, and my permutation matrix is (1,2,0). Then the potential spots for 'E' elements are the following (again, using (row * W + column)):
Here is my main class definition. You don't need to use this, but you may find it useful:
class Matrix { public: int W; int E; int P; /* This is 'x' or 'h' */ vector <int> Perm; /* Permutation of 0 .. (W-1), for the 'X' elements. */ vector <int> Non_X; /* This is the row/col id of each of the non-X elements. */ vector <int> E_ID; /* This is the row/col id of the E elements */ void Print(); /* Print the matrix defined by W, Perm and E_ID */ void Permute(int index); /* This is the recursive permuting method. */ void Choose(int index); /* This is the recursive n-choose-k method. */ }; |
UNIX> matrix_enum 2 1 x | flatten_for_grading | sort .X XE EX X. X. EX XE .X UNIX> matrix_enum 2 1 h | flatten_for_grading | sort 1 3 2 3 3 1 3 2 UNIX>Your output, after being piped through flatten_for_grading and then sort, has to match my output (piped through flatten_for_grading and sort) verbatim. This will be the technique used for gradescripts 0 through 70.
The second technique is to use the program double_check. This takes W, E, and h|x on the command line and then accepts input of your program piped through flatten_for_grading. It then checks every line of input t to see if it is legal for those parameters. This means that for 'x':
XE. EX. ..X |
EX. XE. ..X |
So double_check will allow you to specify (3,3,4) twice, but not three times.
The double_check program prints nothing if its input is legal. If you have a problem, it prints an error message on standard output. For example, here's what happens if you specify (3,3,4) three times in the above example:
UNIX> double_check 3 2 h 3 3 4 3 3 4 3 3 4 Bad line 3: Too many lines (3) with these values. Here are the matrices that correspond to these values: EX. XE. ..X XE. EX. ..X UNIX>Gradescripts 71 through 100 pipe the output of your program through flatten_for_grading, and then through head -n 50000, and then through double_check. This lets me grade for larger values of W and E without waiting for the giant enumerations to complete.
To help you manage your expectations -- the following table contains how long the gradescripts took on my programs (seconds). Most of this time is in double_check, by the way -- please see this Piazza question and answer for more detail on why gradescript 81 takes so long.
1 - 0.08 2 - 0.06 3 - 0.06 4 - 0.06 5 - 0.06 6 - 0.06 7 - 0.07 8 - 0.07 9 - 0.06 10 - 0.06 11 - 1.65 12 - 0.06 13 - 0.81 14 - 0.20 15 - 4.09 16 - 0.37 17 - 0.09 18 - 1.93 19 - 0.66 20 - 0.21 |
21 - 3.31 22 - 0.76 23 - 0.43 24 - 0.09 25 - 1.38 26 - 0.32 27 - 1.71 28 - 1.81 29 - 0.14 30 - 3.17 31 - 0.34 32 - 0.83 33 - 0.44 34 - 2.77 35 - 1.54 36 - 0.07 37 - 0.07 38 - 0.39 39 - 2.07 40 - 3.38 |
41 - 0.06 42 - 2.71 43 - 0.13 44 - 2.01 45 - 0.10 46 - 0.06 47 - 1.27 48 - 0.15 49 - 0.22 50 - 0.18 51 - 0.04 52 - 0.04 53 - 0.04 54 - 0.04 55 - 0.40 56 - 0.05 57 - 0.05 58 - 0.05 59 - 0.04 60 - 0.04 |
61 - 0.29 62 - 0.04 63 - 0.29 64 - 0.35 65 - 0.25 66 - 0.68 67 - 0.06 68 - 0.50 69 - 0.27 70 - 0.22 71 - 0.27 72 - 1.73 73 - 0.42 74 - 0.05 75 - 1.21 76 - 1.17 77 - 1.68 78 - 1.79 79 - 0.49 80 - 2.08 |
81 - 11.78 82 - 1.00 83 - 0.77 84 - 1.53 85 - 1.52 86 - 2.20 87 - 0.53 88 - 0.52 89 - 0.41 90 - 2.65 91 - 2.40 92 - 1.48 93 - 1.80 94 - 0.78 95 - 0.63 96 - 1.76 97 - 1.17 98 - 0.57 99 - 0.30 100 - 2.38 |