#include <unistd.h>
#define MAX_SOLUTIONS 100 // Define a maximum number of solutions to store
typedef struct {
int solutions[100][4];
int count;
} SolutionTable;
// Initialize the solution table
void initialize_solution_table(SolutionTable *table) {
table->count = 0;
}
// Store a valid configuration in the SolutionTable
void store_solution(SolutionTable *table, int *input) {
if (table->count < MAX_SOLUTIONS) {
for (int i = 0; i < 4; i++) {
table->solutions[table->count][i] = input[i];
}
table->count++;
}
}
void initialize_grid(int result[4][4]) {
int i = 0;
int j;
while (i < 4) {
j = 0;
while (j < 4) {
result[i][j] = 0;
j++;
}
i++;
}
}
void print_result(int result[4][4]) {
int i = 0;
int j;
char num;
while (i < 4) {
j = 0;
while (j < 4) {
num = result[i][j] + '0';
write(1, &num, 1);
if (j < 3) {
write(1, " ", 1);
}
j++;
}
write(1, "\n", 1);
i++;
}
}
// Modified print_final_combinations function that prints only the valid combinations
void print_final_combinations(int final_tables[MAX_SOLUTIONS][4][4], int final_count) {
char newline = '\n';
if (final_count == 0) {
write(1, "No valid combinations found.\n", 29);
return;
}
for (int i = 0; i < final_count; i++) {
write(1, "Combination:\n", 13);
print_result(final_tables[i]);
write(1, &newline, 1); // Print a newline between tables for better readability
}
}
void fill_easy_cases_rows(int *left_clues, int *right_clues, int result[4][4]) {
int i, j;
for (i = 0; i < 4; i++) {
if (left_clues[i] == 4) {
for (j = 0; j < 4; j++) {
result[i][j] = j + 1;
}
} else if (left_clues[i] == 1) {
result[i][0] = 4;
}
if (right_clues[i] == 4) {
for (j = 0; j < 4; j++) {
result[i][j] = 4 - j;
}
} else if (right_clues[i] == 1) {
result[i][3] = 4;
}
if (left_clues[i] == 2 && right_clues[i] == 1)
result[i][0] = 3;
if (left_clues[i] == 1 && right_clues[i] == 2)
result[i][3] = 3;
}
}
void fill_easy_cases_cols(int *up_clues, int *down_clues, int result[4][4]) {
int i, j;
for (i = 0; i < 4; i++) {
if (up_clues[i] == 4) {
for (j = 0; j < 4; j++) {
result[j][i] = j + 1;
}
} else if (up_clues[i] == 1) {
result[0][i] = 4;
}
if (down_clues[i] == 4) {
for (j = 0; j < 4; j++) {
result[j][i] = 4 - j;
}
} else if (down_clues[i] == 1) {
result[3][i] = 4;
}
if (up_clues[i] == 2 && down_clues[i] == 1)
result[0][i] = 3;
if (up_clues[i] == 1 && down_clues[i] == 2)
result[3][i] = 3;
}
}
// Checks if a row satisfies the left and right clues
int is_valid_view(int *tab, int l_clue, int r_clue) {
int count = 0, max_height = 0;
int i = 0;
// Check left view
while (i < 4) {
if (tab[i] > max_height) {
count++;
max_height = tab[i];
}
i++;
}
if (count != l_clue) {
return 0;
}
// Check right view
count = 0;
max_height = 0;
i = 3;
while (i >= 0) {
if (tab[i] > max_height) {
count++;
max_height = tab[i];
}
i--;
}
return count == r_clue;
}
// Finds missing numbers in a row or column
void find_missing_numbers(int *input, int *missing, int *missing_count) {
int used[5] = {0}, i = 0;
while (i < 4) {
if (input[i] > 0 && input[i] <= 4) {
used[input[i]] = 1;
}
i++;
}
*missing_count = 0;
i = 1;
while (i <= 4) {
if (!used[i]) {
missing[(*missing_count)++] = i;
}
i++;
}
}
// Generates permutations for rows/columns and checks validity
void generate_permutations(int *input, int *missing, int missing_count, int index, int l_clue, int r_clue, SolutionTable *table) {
if (index == 4) {
if (is_valid_view(input, l_clue, r_clue)) {
store_solution(table, input); // Store the valid configuration
}
return;
}
if (input[index] != 0) {
generate_permutations(input, missing, missing_count, index + 1, l_clue, r_clue, table);
} else {
for (int i = 0; i < missing_count; i++) {
int current_value = missing[i];
int already_used = 0;
for (int j = 0; j < index; j++) {
if (input[j] == current_value) {
already_used = 1;
break;
}
}
if (!already_used) {
input[index] = current_value;
generate_permutations(input, missing, missing_count, index + 1, l_clue, r_clue, table);
input[index] = 0;
}
}
}
}
void compare_solutions(SolutionTable *rows, SolutionTable *colms, SolutionTable better_solutions[4]) {
// Initialize better_solutions counts to zero
for (int i = 0; i < 4; i++) {
better_solutions[i].count = 0; // Set count to zero for each SolutionTable
}
// Iterate through each row table
for (int k = 0; k < 4; k++) {
// Initialize c for each row
for (int c = 0; c < rows[k].count; c++) {
int verifier = 0; // Reset verifier for each combination
// Check each solution against the columns
for (int j = 0; j < 4; j++) { // Loop through all columns (0 to 3)
int d = 0;
while (d < colms[j].count) {
// Compare solutions in rows and columns
if (rows[k].solutions[c][j] == colms[j].solutions[d][k]) {
verifier++; // Increment verifier on match
break; // Stop checking other column entries once a match is found
}
d++;
}
}
// If all four elements matched, add the solution to better_solutions
if (verifier == 4) {
// Copy the solution into better_solutions
for (int m = 0; m < 4; m++) {
better_solutions[k].solutions[better_solutions[k].count][m] = rows[k].solutions[c][m];
}
better_solutions[k].count++; // Increment count of better solutions
}
}
}
}
// Function to check if any row in better_solutions is empty
int check_empty_rows(SolutionTable better_solutions[4]) {
for (int i = 0; i < 4; i++) {
if (better_solutions[i].count == 0) {
return 1; // Return 1 if any row is empty
}
}
return 0; // Return 0 if all rows have at least one solution
}
// Function to check if a column has unique elements (no duplicates)
int is_column_unique(int final_table[4][4], int col_index) {
int seen[5] = {0}; // Array to track which numbers (1 to 4) have been seen
for (int i = 0; i < 4; i++) {
int value = final_table[i][col_index];
if (seen[value]) {
return 0; // Duplicate found, return false
}
seen[value] = 1; // Mark the number as seen
}
return 1; // All elements are unique
}
// Function to validate all columns and check for uniqueness and view correctness
int are_columns_valid(int final_table[4][4], int *up_clues, int *down_clues) {
for (int col = 0; col < 4; col++) {
// Check if the column has unique elements
if (!is_column_unique(final_table, col)) {
return 0; // Column has duplicates, return false
}
// Extract the column into a temporary array to check the views
int column[4];
for (int row = 0; row < 4; row++) {
column[row] = final_table[row][col];
}
// Check if the column satisfies the up and down clues
if (!is_valid_view(column, up_clues[col], down_clues[col])) {
return 0; // Column does not satisfy the view clues, return false
}
}
return 1; // All columns are valid
}
// Modified function to generate and validate combinations
void generate_combinations(SolutionTable better_solutions[4], int final_tables[MAX_SOLUTIONS][4][4], int *final_count, int *up_clues, int *down_clues) {
*final_count = 0; // Initialize final count to 0
for (int i = 0; i < better_solutions[0].count; i++) {
for (int j = 0; j < better_solutions[1].count; j++) {
for (int k = 0; k < better_solutions[2].count; k++) {
for (int l = 0; l < better_solutions[3].count; l++) {
// Copy the current row configurations into the final table
for (int col = 0; col < 4; col++) {
final_tables[*final_count][0][col] = better_solutions[0].solutions[i][col];
final_tables[*final_count][1][col] = better_solutions[1].solutions[j][col];
final_tables[*final_count][2][col] = better_solutions[2].solutions[k][col];
final_tables[*final_count][3][col] = better_solutions[3].solutions[l][col];
}
// Validate columns: check for duplicates and view correctness
if (are_columns_valid(final_tables[*final_count], up_clues, down_clues)) {
(*final_count)++; // Increment the count of valid combinations
}
}
}
}
}
}
void solvesky(char *input) {
int result[4][4];
int data[4][4];
int i = 0;
SolutionTable rows_posiblets[4];
SolutionTable colms_posiblets[4];
int missing[4];
int missing_count;
SolutionTable better_solutions[4]; // Declare better_solutions array
initialize_grid(result);
// Parse the input clues (up, down, left, right)
while (i < 4) {
data[0][i] = input[2 * i] - '0'; // up clues
data[1][i] = input[2 * (i + 4)] - '0'; // down clues
data[2][i] = input[2 * (i + 8)] - '0'; // left clues
data[3][i] = input[2 * (i + 12)] - '0'; // right clues
i++;
}
// Initialize the possible solution tables
for (i = 0; i < 4; i++) {
initialize_solution_table(&rows_posiblets[i]);
initialize_solution_table(&colms_posiblets[i]);
}
// Fill easy cases
fill_easy_cases_rows(data[2], data[3], result); // Process rows
fill_easy_cases_cols(data[0], data[1], result); // Process columns
// Generate permutations for rows and columns
for (i = 0; i < 4; i++) {
find_missing_numbers(result[i], missing, &missing_count);
generate_permutations(result[i], missing, missing_count, 0, data[2][i], data[3][i], &rows_posiblets[i]);
find_missing_numbers(result[i], missing, &missing_count);
generate_permutations(result[i], missing, missing_count, 0, data[0][i], data[1][i], &colms_posiblets[i]);
}
// Compare solutions and store the best ones
compare_solutions(rows_posiblets, colms_posiblets, better_solutions);
// Check if any row is empty
if (check_empty_rows(better_solutions)) {
write(1, "Error: impossible selution \n", 33);
return;
}
int final_tables[100][4][4]; // 3D array to store all combinations
int final_count = 0; // Total number of 2D tables generated
// Generate combinations and store them in final_tables
generate_combinations(better_solutions, final_tables, &final_count,data[0], data[1]);
// Print all final combinations
print_final_combinations(final_tables, final_count);
}
int main(int argc, char **argv) {
if (argc == 2) {
solvesky("3 1 2 3 1 3 3 2 2 3 2 1 3 2 1 2");
} else {
write(1, "Error\n", 6);
}
return 0;
}