diff --git a/solutions/c/zebra-puzzle/1/zebra_puzzle.c b/solutions/c/zebra-puzzle/1/zebra_puzzle.c new file mode 100644 index 0000000..0a12786 --- /dev/null +++ b/solutions/c/zebra-puzzle/1/zebra_puzzle.c @@ -0,0 +1,113 @@ +#include "zebra_puzzle.h" +#include + +// typedef struct { +// const char *drinks_water; +// const char *owns_zebra; +// } solution_t; + +typedef enum { COLORS, NATIONS, DRINKS, HOBBIES, PETS, DONE } level_t; + +enum { RED, GREEN, IVORY, YELLOW, BLUE }; +enum { DOG, SNAIL, FOX, HORSE, ZEBRA }; +enum { COFFEE, TEA, MILK, ORANGE_JUICE, WATER }; +enum { ENGLISH, SPANIARD, UKRAINIAN, NORWEGIAN, JAPANESE }; +enum { DANCING, PAINTING, READING, FOOTBALL, CHESS }; + +int state[5][5]; + +static inline bool next_to(int a, int b) { + return (a - b == 1) || (b - a == 1); +} + +static inline void swap(int *n1, int *n2) { + int temp = *n1; + *n1 = *n2; + *n2 = temp; +} + +// There are five houses. +// The Englishman lives in the red house. +// The Spaniard owns the dog. +// The person in the green house drinks coffee. +// The Ukrainian drinks tea. +// The green house is immediately to the right of the ivory house. +// The snail owner likes to go dancing. +// The person in the yellow house is a painter. +// The person in the middle house drinks milk. +// The Norwegian lives in the first house. +// The person who enjoys reading lives in the house next to the person with the fox. +// The painter's house is next to the house with the horse. +// The person who plays football drinks orange juice. +// The Japanese person plays chess. +// The Norwegian lives next to the blue house. + +static inline bool is_valid(level_t level) { + if (level >= COLORS) { + if (state[COLORS][GREEN] != state[COLORS][IVORY] + 1) return false; + } + if (level >= NATIONS) { + if (state[NATIONS][NORWEGIAN] != 0) return false; + if (state[NATIONS][ENGLISH] != state[COLORS][RED]) return false; + if (!next_to(state[NATIONS][NORWEGIAN], state[COLORS][BLUE])) return false; + } + if (level >= DRINKS) { + if (state[DRINKS][MILK] != 2) return false; + if (state[DRINKS][COFFEE] != state[COLORS][GREEN]) return false; + if (state[NATIONS][UKRAINIAN] != state[DRINKS][TEA]) return false; + } + if (level >= HOBBIES) { + if (state[COLORS][YELLOW] != state[HOBBIES][PAINTING]) return false; + if (state[HOBBIES][FOOTBALL] != state[DRINKS][ORANGE_JUICE]) return false; + if (state[NATIONS][JAPANESE] != state[HOBBIES][CHESS]) return false; + } + if (level >= PETS) { + if (state[NATIONS][SPANIARD] != state[PETS][DOG]) return false; + if (state[PETS][SNAIL] != state[HOBBIES][DANCING]) return false; + if (!next_to(state[HOBBIES][READING], state[PETS][FOX])) return false; + if (!next_to(state[HOBBIES][PAINTING], state[PETS][HORSE])) return false; + } + return true; +} + +static bool backtrack(level_t level, int* current_perm, int start) { + if (level == DONE) return true; + + if (start == 5) { + if (is_valid(level)) { + int next_p[5] = {0, 1, 2, 3, 4}; + return backtrack(level + 1, next_p, 0); + } + return false; + } + + for (int i = start; i < 5; i++) { + swap(¤t_perm[start], ¤t_perm[i]); + + state[level][start] = current_perm[start]; + + if (backtrack(level, current_perm, start + 1)) return true; + + swap(¤t_perm[start], ¤t_perm[i]); + } + return false; +} + +solution_t solve_puzzle(void){ + + int first_perm[5] = {0, 1, 2, 3, 4}; + backtrack(COLORS, first_perm, 0); + + solution_t sol; +// enum { ENGLISH, SPANIARD, UKRAINIAN, NORWEGIAN, JAPANESE }; + const char* nations[] = {"Englishman", "Spaniard", "Ukrainian", "Norwegian", "Japanese"}; + + for(int i=0; i<5; i++) { + if (state[NATIONS][i] == state[DRINKS][WATER]) sol.drinks_water = nations[i]; + if (state[NATIONS][i] == state[PETS][ZEBRA]) sol.owns_zebra = nations[i]; + } + + return sol; + +} + diff --git a/solutions/c/zebra-puzzle/1/zebra_puzzle.h b/solutions/c/zebra-puzzle/1/zebra_puzzle.h new file mode 100644 index 0000000..4ef36c2 --- /dev/null +++ b/solutions/c/zebra-puzzle/1/zebra_puzzle.h @@ -0,0 +1,11 @@ +#ifndef ZEBRA_PUZZLE_H +#define ZEBRA_PUZZLE_H + +typedef struct { + const char *drinks_water; + const char *owns_zebra; +} solution_t; + +solution_t solve_puzzle(void); + +#endif