A binary 8x8 matrix is 'unholy' if there are no isolated 1s. A 1 is isolated if there isn't another 1 in any of the 4 direct cardinal directions. Write a C program that counts the total number of unholy 8x8 matricies.To solve this question: - Use bit arithmetic and an unsigned long to represent the matrix. - Write a function is_unholy that tests if a matrix is unholy by bit-shifting and masking. Use a dynamic program to count the number of unholy matricies. - Recurse on the number of rows the matrix has. - Enumerate all 2^16 next two rows. This is enough to completely isolate the prior solutions from the next. Write out a plan for the program, and then implement the plan in C.
A binary 8x8 matrix is 'unholy' if there are no isolated 1s. A 1 is isolated if there isn't another 1 in any of the 4 direct cardinal directions. Write a C program that counts the total number of unholy 8x8 matricies.To solve this question: - Use bit arithmetic and an unsigned long to represent the matrix. - Write a function is_unholy that tests if a matrix is unholy by bit-shifting and masking. Use a dynamic program to count the number of unholy matricies. - Recurse on the number of rows the matrix has. - Enumerate all 2^16 next two rows. This is enough to completely isolate the prior solutions from the next. Write out a plan for the program, and then implement the plan in C.
### Plan for the Program 1. **Representation of the Matrix**: - Represent each row of the 8x8 matrix as an 8-bit unsigned integer (`uint8_t`). - The entire matrix can be represented as an array of 8 `uint8_t` values. 2. **Check if a Matrix is Unholy**: - Define a function `is_unholy` that takes the matrix as input. - For each cell in the matrix, check if it is a `1` and if it has at least one neighboring `1` in the four cardinal directions (up, down, left, right). - If any `1` is found to be isolated, the matrix is not unholy. 3. **Dynamic Programming Approach**: - Use dynamic programming to count the number of unholy matrices. - Recurse on the number of rows, considering all possible combinations of rows. - Use a memoization table to store intermediate results and avoid redundant calculations. 4. **Enumerate All Possible Rows**: - Since each row is an 8-bit integer, there are `2^8 = 256` possible rows. - Enumerate all possible pairs of rows to ensure that the constraints are satisfied. 5. **Count Unholy Matrices**: - Use the dynamic programming approach to count all possible 8x8 matrices that are unholy. ### Implementation in C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #define ROWS 8 #define COLS 8 // Function to check if a matrix is unholy bool is_unholy(uint8_t matrix[ROWS]) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (matrix[i] & (1 << j)) { bool has_neighbor = false; // Check left if (j > 0 && (matrix[i] & (1 << (j - 1)))) has_neighbor = true; // Check right if (j < COLS - 1 && (matrix[i] & (1 << (j + 1)))) has_neighbor = true; // Check up if (i > 0 && (matrix[i - 1] & (1 << j))) has_neighbor = true; // Check down if (i < ROWS - 1 && (matrix[i + 1] & (1 << j))) has_neighbor = true; if (!has_neighbor) return false; } } } return true; } // Dynamic programming function to count unholy matrices uint64_t count_unholy_matrices() { uint64_t dp[ROWS + 1][1 << COLS]; memset(dp, 0, sizeof(dp)); // Base case: empty matrix is considered unholy dp[0][0] = 1; for (int i = 1; i <= ROWS; i++) { for (int prev_mask = 0; prev_mask < (1 << COLS); prev_mask++) { for (int curr_mask = 0; curr_mask < (1 << COLS); curr_mask++) { uint8_t matrix[ROWS]; matrix[i - 1] = curr_mask; if (i > 1) matrix[i - 2] = prev_mask; if (is_unholy(matrix)) { dp[i][curr_mask] += dp[i - 1][prev_mask]; } } } } uint64_t total = 0; for (int mask = 0; mask < (1 << COLS); mask++) { total += dp[ROWS][mask]; } return total; } int main() { uint64_t total_unholy = count_unholy_matrices(); printf("Total number of unholy 8x8 matrices: %llu\n", total_unholy); return 0; } |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #define ROWS 8 #define COLS 8 // Function to check if a matrix is unholy bool is_unholy(uint8_t matrix[ROWS]) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (matrix[i] & (1 << j)) { bool has_neighbor = false; // Check left if (j > 0 && (matrix[i] & (1 << (j - 1)))) has_neighbor = true; // Check right if (j < COLS - 1 && (matrix[i] & (1 << (j + 1)))) has_neighbor = true; // Check up if (i > 0 && (matrix[i - 1] & (1 << j))) has_neighbor = true; // Check down if (i < ROWS - 1 && (matrix[i + 1] & (1 << j))) has_neighbor = true; if (!has_neighbor) return false; } } } return true; } // Dynamic programming function to count unholy matrices uint64_t count_unholy_matrices() { uint64_t dp[ROWS + 1][1 << COLS]; memset(dp, 0, sizeof(dp)); // Base case: empty matrix is considered unholy dp[0][0] = 1; for (int i = 1; i <= ROWS; i++) { for (int prev_mask = 0; prev_mask < (1 << COLS); prev_mask++) { for (int curr_mask = 0; curr_mask < (1 << COLS); curr_mask++) { uint8_t matrix[ROWS]; matrix[i - 1] = curr_mask; if (i > 1) matrix[i - 2] = prev_mask; if (is_unholy(matrix)) { dp[i][curr_mask] += dp[i - 1][prev_mask]; } } } } uint64_t total = 0; for (int mask = 0; mask < (1 << COLS); mask++) { total += dp[ROWS][mask]; } return total; } int main() { uint64_t total_unholy = count_unholy_matrices(); printf("Total number of unholy 8x8 matrices: %llu\n", total_unholy); return 0; } |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #define ROWS 8 #define COLS 8 // Function to check if a matrix is unholy bool is_unholy(uint8_t matrix[ROWS]) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (matrix[i] & (1 << j)) { bool has_neighbor = false; // Check left if (j > 0 && (matrix[i] & (1 << (j - 1)))) has_neighbor = true; // Check right if (j < COLS - 1 && (matrix[i] & (1 << (j + 1)))) has_neighbor = true; // Check up if (i > 0 && (matrix[i - 1] & (1 << j))) has_neighbor = true; // Check down if (i < ROWS - 1 && (matrix[i + 1] & (1 << j))) has_neighbor = true; if (!has_neighbor) return false; } } } return true; } // Dynamic programming function to count unholy matrices uint64_t count_unholy_matrices() { uint64_t dp[ROWS + 1][1 << COLS]; memset(dp, 0, sizeof(dp)); // Base case: empty matrix is considered unholy dp[0][0] = 1; for (int i = 1; i <= ROWS; i++) { for (int prev_mask = 0; prev_mask < (1 << COLS); prev_mask++) { for (int curr_mask = 0; curr_mask < (1 << COLS); curr_mask++) { uint8_t matrix[ROWS]; matrix[i - 1] = curr_mask; if (i > 1) matrix[i - 2] = prev_mask; if (is_unholy(matrix)) { dp[i][curr_mask] += dp[i - 1][prev_mask]; } } } } uint64_t total = 0; for (int mask = 0; mask < (1 << COLS); mask++) { total += dp[ROWS][mask]; } return total; } int main() { uint64_t total_unholy = count_unholy_matrices(); printf("Total number of unholy 8x8 matrices: %llu\n", total_unholy); return 0; } |
Total number of unholy 8x8 matrices: 53003772538202116
main.c: In function 'main':
main.c:63:53: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'uint64_t' {aka 'long unsigned int'} [-Wformat=]
63 | printf("Total number of unholy 8x8 matrices: %llu\n", total_unholy);
| ~~~^ ~~~~~~~~~~~~
| | |
| | uint64_t {aka long unsigned int}
| long long unsigned int
| %lu
Testing if the previous output contains the string 1121231537486377866
: False