#include <stdio.h>

char *NationS[] = {"British", "Swedish", "Danish", "Norvegian", "German"};
enum Nation {British, Swedish, Danish, Norvegian, German};
char *NumberS[] = {"One", "Two", "Three", "Four", "Five"};
enum Number {One, Two, Three, Four, Five};
char *ColourS[] = {"Red", "Green", "Blue", "White", "Yellow"};
enum Colour {Red, Green, Blue, White, Yellow};
char *DrinkS[] = {"Milk", "Coffee", "Water", "Beer", "Tea"};
enum Drink {Milk, Coffee, Water, Beer, Tea};
char *SmokeS[] = {"PallMall", "Dunhill", "Blend", "BlueMaster", "Prince"};
enum Smoke {PallMall, Dunhill, Blend, BlueMaster, Prince};
char *PetS[] = {"Dog", "Cat", "Fish", "Horse", "Bird"};
enum Pet {Dog, Cat, Fish, Horse, Bird};

#define TRUE 1
#define FALSE 0

void
myprint(char *ptr, char **s)
{
  printf("%12s%12s%12s%12s%12s\n", s[ptr[0]], s[ptr[1]], s[ptr[2]], s[ptr[3]], s[ptr[4]]);
}

char perms[][5] = {
  {     4,     3,     2,     1,     0},
  {     3,     4,     2,     1,     0},
  {     4,     2,     3,     1,     0},
  {     2,     4,     3,     1,     0},
  {     3,     2,     4,     1,     0},
  {     2,     3,     4,     1,     0},
  {     4,     3,     1,     2,     0},
  {     3,     4,     1,     2,     0},
  {     4,     1,     3,     2,     0},
  {     1,     4,     3,     2,     0},
  {     3,     1,     4,     2,     0},
  {     1,     3,     4,     2,     0},
  {     4,     2,     1,     3,     0},
  {     2,     4,     1,     3,     0},
  {     4,     1,     2,     3,     0},
  {     1,     4,     2,     3,     0},
  {     2,     1,     4,     3,     0},
  {     1,     2,     4,     3,     0},
  {     3,     2,     1,     4,     0},
  {     2,     3,     1,     4,     0},
  {     3,     1,     2,     4,     0},
  {     1,     3,     2,     4,     0},
  {     2,     1,     3,     4,     0},
  {     1,     2,     3,     4,     0},
  {     4,     3,     2,     0,     1},
  {     3,     4,     2,     0,     1},
  {     4,     2,     3,     0,     1},
  {     2,     4,     3,     0,     1},
  {     3,     2,     4,     0,     1},
  {     2,     3,     4,     0,     1},
  {     4,     3,     0,     2,     1},
  {     3,     4,     0,     2,     1},
  {     4,     0,     3,     2,     1},
  {     0,     4,     3,     2,     1},
  {     3,     0,     4,     2,     1},
  {     0,     3,     4,     2,     1},
  {     4,     2,     0,     3,     1},
  {     2,     4,     0,     3,     1},
  {     4,     0,     2,     3,     1},
  {     0,     4,     2,     3,     1},
  {     2,     0,     4,     3,     1},
  {     0,     2,     4,     3,     1},
  {     3,     2,     0,     4,     1},
  {     2,     3,     0,     4,     1},
  {     3,     0,     2,     4,     1},
  {     0,     3,     2,     4,     1},
  {     2,     0,     3,     4,     1},
  {     0,     2,     3,     4,     1},
  {     4,     3,     1,     0,     2},
  {     3,     4,     1,     0,     2},
  {     4,     1,     3,     0,     2},
  {     1,     4,     3,     0,     2},
  {     3,     1,     4,     0,     2},
  {     1,     3,     4,     0,     2},
  {     4,     3,     0,     1,     2},
  {     3,     4,     0,     1,     2},
  {     4,     0,     3,     1,     2},
  {     0,     4,     3,     1,     2},
  {     3,     0,     4,     1,     2},
  {     0,     3,     4,     1,     2},
  {     4,     1,     0,     3,     2},
  {     1,     4,     0,     3,     2},
  {     4,     0,     1,     3,     2},
  {     0,     4,     1,     3,     2},
  {     1,     0,     4,     3,     2},
  {     0,     1,     4,     3,     2},
  {     3,     1,     0,     4,     2},
  {     1,     3,     0,     4,     2},
  {     3,     0,     1,     4,     2},
  {     0,     3,     1,     4,     2},
  {     1,     0,     3,     4,     2},
  {     0,     1,     3,     4,     2},
  {     4,     2,     1,     0,     3},
  {     2,     4,     1,     0,     3},
  {     4,     1,     2,     0,     3},
  {     1,     4,     2,     0,     3},
  {     2,     1,     4,     0,     3},
  {     1,     2,     4,     0,     3},
  {     4,     2,     0,     1,     3},
  {     2,     4,     0,     1,     3},
  {     4,     0,     2,     1,     3},
  {     0,     4,     2,     1,     3},
  {     2,     0,     4,     1,     3},
  {     0,     2,     4,     1,     3},
  {     4,     1,     0,     2,     3},
  {     1,     4,     0,     2,     3},
  {     4,     0,     1,     2,     3},
  {     0,     4,     1,     2,     3},
  {     1,     0,     4,     2,     3},
  {     0,     1,     4,     2,     3},
  {     2,     1,     0,     4,     3},
  {     1,     2,     0,     4,     3},
  {     2,     0,     1,     4,     3},
  {     0,     2,     1,     4,     3},
  {     1,     0,     2,     4,     3},
  {     0,     1,     2,     4,     3},
  {     3,     2,     1,     0,     4},
  {     2,     3,     1,     0,     4},
  {     3,     1,     2,     0,     4},
  {     1,     3,     2,     0,     4},
  {     2,     1,     3,     0,     4},
  {     1,     2,     3,     0,     4},
  {     3,     2,     0,     1,     4},
  {     2,     3,     0,     1,     4},
  {     3,     0,     2,     1,     4},
  {     0,     3,     2,     1,     4},
  {     2,     0,     3,     1,     4},
  {     0,     2,     3,     1,     4},
  {     3,     1,     0,     2,     4},
  {     1,     3,     0,     2,     4},
  {     3,     0,     1,     2,     4},
  {     0,     3,     1,     2,     4},
  {     1,     0,     3,     2,     4},
  {     0,     1,     3,     2,     4},
  {     2,     1,     0,     3,     4},
  {     1,     2,     0,     3,     4},
  {     2,     0,     1,     3,     4},
  {     0,     2,     1,     3,     4},
  {     1,     0,     2,     3,     4},
  {     0,     1,     2,     3,     4}
};


char
possible(char *number, char *colour, char* drink, char *smoke, char *pet)
{
  // Rules, with the rule number as a comment
  
  // single property rules
  if(number != NULL && number[Norvegian] != One) // 9
    return FALSE;
  if(colour != NULL && colour[British] != Red) // 1
    return FALSE;
  if(drink != NULL && drink[Danish] != Tea)  // 3
    return FALSE;
  if(smoke != NULL && smoke[German] != Prince) // 13
    return FALSE;
  if(pet != NULL && pet[Swedish] != Dog)    // 2
    return FALSE;
  

  // only check complicated rules, if everything is defined

  if(number == NULL || 
     colour == NULL || 
     drink == NULL || 
     smoke == NULL ||
     pet == NULL)
    return TRUE;

  // double property rules
 
  int i, j, diff;

  for(i = 0; i < 5; i++){
    if(colour[i] == Green && drink[i] != Coffee) // 5
      return FALSE;
    if(smoke[i] == PallMall && pet[i] != Bird) // 6
      return FALSE;
    if(colour[i] == Yellow && smoke[i] != Dunhill) // 7
      return FALSE;
    if(number[i] == Three && drink[i] != Milk) // 8
      return FALSE;
    if(smoke[i] == BlueMaster && drink[i] != Beer) // 12
      return FALSE;
    if(colour[i] == Blue && number[i] != Two) // 14
      return FALSE;
    
    // double person double property rules
    
    for(j = 0; j < 5; j++){
      
      if(colour[i] == Green && colour[j] == White && number[j] - number[i] != 1) // 4
	return FALSE;
      
      diff = number[i]-number[j];
      if(diff < 0) diff = -diff;
      
      if(smoke[i] == Blend && pet[j] == Cat && diff != 1) // 10
	return FALSE;
      if(pet[i] == Horse && smoke[j] == Dunhill && diff != 1) // 11
	return FALSE;
      if(smoke[i] == Blend && drink[j] == Water && diff != 1) // 15
	return FALSE;
    }
  }

  return TRUE;
}



main()
{

  char nation[5] = {British, Swedish, Danish, Norvegian, German};
  char *number = NULL;
  char *colour = NULL;
  char *drink = NULL;
  char *smoke = NULL;
  char *pet = NULL;

  char i1, i2, i3, i4, i5;

  for(i1 = 0; i1 < 120; i1++){
    number = perms[i1];
    if(possible(number, colour, drink, smoke, pet))
      for(i2 = 0; i2 < 120; i2++){
	colour = perms[i2];
	if(possible(number, colour, drink, smoke, pet))
	  for(i3 = 0; i3 < 120; i3++){
	    drink = perms[i3];
	    if(possible(number, colour, drink, smoke, pet))
	      for(i4 = 0; i4 < 120; i4++){
		smoke = perms[i4];
		if(possible(number, colour, drink, smoke, pet))
		  for(i5 = 0; i5 < 120; i5++){
		    pet = perms[i5];
		    
		    if(possible(number, colour, drink, smoke, pet)){
		      // woo-hoo!
		      printf("Found a solution:\n");
		      printf("Nation: ");
		      myprint(nation, NationS);
		      printf("Number: ");
		      myprint(number, NumberS);
		      printf("Colour: ");
		      myprint(colour, ColourS);
		      printf("Drink : ");
		      myprint(drink, DrinkS);
		      printf("Smoke : ");
		      myprint(smoke, SmokeS);
		      printf("Pet   : ");
		      myprint(pet, PetS);
		      printf("\n");
		    }
		    
		  }
		pet = NULL;
	      }
	    smoke = NULL;
	  }
	drink = NULL;
      }
    colour = NULL;
  }
  
}

