Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions solutions/c/zebra-puzzle/1/zebra_puzzle.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "zebra_puzzle.h"
#include <stdbool.h>

// 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(&current_perm[start], &current_perm[i]);

state[level][start] = current_perm[start];

if (backtrack(level, current_perm, start + 1)) return true;

swap(&current_perm[start], &current_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;

}

11 changes: 11 additions & 0 deletions solutions/c/zebra-puzzle/1/zebra_puzzle.h
Original file line number Diff line number Diff line change
@@ -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