MENSA triangle riddle

Discussion in 'General Discussion' started by TekkenMaster, Feb 17, 2005.

  1. Simon F

    Simon F Tea maker
    Moderator Veteran

    Joined:
    Feb 8, 2002
    Messages:
    4,563
    Likes Received:
    171
    Location:
    In the Island of Sodor, where the steam trains lie
    Which'd probably mean it was about 20~30 lines of code :)
     
  2. cristic

    Newcomer

    Joined:
    Jan 30, 2004
    Messages:
    179
    Likes Received:
    0
    Location:
    nowhere near
    Ah, memories, that made me dig up that old homework... :)
    Actually the riddle was not the same, but a similiar one:


    On a street, there are five houses. There is a man living in each house. They all have different nationalities, different pets, different color, smoking and drinking preferences. What we know is:

    * the Englishman lives in the red house
    * the man living in the green house drinks coffee
    * the Italian drinks tea
    * the man living in the yellow house smokes Kent
    * the man drinking milk lives in the middle house
    * the Russian lives in the leftmost house
    * the man smoking Marlboro lives next to the man having a fox
    * the man smoking Kent lives next to the man having a horse
    * the man drinking juice smokes Pall Mall
    * the Japanese smokes Assos
    * the Russian lives next to the blue house
    * the Spanish has a dog
    * the man having a snake smokes Camel
    * the grey house lies near the green house
    * the man having a cat and the man drinking vodka live in the lateral houses

    You are invited to manually find an answer to the following question: "Find a suitable distribution of nationalities, pets, colors, cigarettes and drinks, so that all the above requirements are satisfied".


    And the grand solution was a little bit longer than 20-30 lines of code... though I wouldn't know how to make it more concise. :|

    Code:
    solve(S) :-
    	S = [_,_,_,_,_],
    	nationality(O1,englishman),color(O1,red),member(O1,S),
    	color(O2,green),drink(O2,coffee),member(O2,S),
    	nationality(O3,italian),drink(O3,tea),member(O3,S),
    	color(O4,yellow),cigarette(O4,kent),member(O4,S),
    	drink(O5,milk),middle(O5,S),
    	nationality(O6,russian),leftmost(O6,S),
    	cigarette(OA7,marlboro),pet(OB7,fox),near(OA7,OB7,S),
    	cigarette(OA8,kent),pet(OB8,horse),near(OA8,OB8,S),
    	drink(O9,juice),cigarette(O9,pall_mall),member(O9,S),
    	nationality(O10,japanese),cigarette(O10,assos),member(O10,S),
    	nationality(OA11,russian),color(OB11,blue),near(OA11,OB11,S),
    	nationality(O12,spanish),pet(O12,dog),member(O12,S),
    	pet(O13,snake),cigarette(O13,camel),member(O13,S),
    	color(OA14,grey),color(OB14,green),near(OA14,OB14,S),
    	pet(OA15,cat),drink(OB15,vodka),lateral(OA15,S),lateral(OB15,S).
    
    color([Color,_,_,_,_],Color).
    
    nationality([_,Nationality,_,_,_],Nationality).
    
    drink([_,_,Drink,_,_],Drink).
    
    cigarette([_,_,_,Cigarette,_],Cigarette).
    
    pet([_,_,_,_,Pet],Pet).
    
    leftmost(X,[X,_,_,_,_]).
    
    middle(X,[_,_,X,_,_]).
    
    lateral(X,[X,_,_,_,_]).
    lateral(X,[_,_,_,_,X]).
    
    left(A,B,S) :-
    	append(_,[A,B|_],S).
    
    near(A,B,S) :-
    	left(A,B,S).
    near(A,B,S) :-
    	left(B,A,S).
    
    Now you can ask the inference machine this query and it'll give you an answer:

    Code:
    ?- solve(S).
    
    S = [[yellow,russian,vodka,kent,fox], [blue,italian,tea,marlboro,horse], [red,englishman,milk,camel,snake], [grey,spanish,juice,pall_mall,dog], [green,japanese,coffee,assos,cat]] ;
    
    No
    
     
  3. Basic

    Regular

    Joined:
    Feb 8, 2002
    Messages:
    846
    Likes Received:
    13
    Location:
    Linköping, Sweden
    OK, I guess there has gone long enough to give a C-solution without any hiding. So here's the C-hack version of cristic's quiz (Oooh, 15 nested loops this time).
    Code:
    #include <stdio.h>
    
    char*   unknown = "?";
    #define Known(X) ((X)!=unknown)
    
    #define CheckAll(I, P1, V1, P2, V2) \
      for(I=0; I<5; I++) {\
        char **p1=&P1[I], **p2=&P2[I];\
        if(Known(*p1)) continue; \
        if(Known(*p2)) continue; \
        *p1=V1; *p2=V2;
    
    #define CheckDist(I, I0, D, P1, V1) \
      for(I=I0-D; I<=I0+D; I+=2*D) {\
        char **p1=&P1[I], **p2=&P1[I];\
        if(I<0 || I>4) continue; \
        if(Known(*p1)) continue; \
        *p1=V1;
    
    #define EndCheck() \
      *p1 = *p2 = unknown; }
    
    int main(int argc, char* argv[])
    {
      int i,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14;
      char *nat[5], *col[5], *dri[5], *cig[5], *pet[5];
    
      for(i=0; i<5; i++) 
        nat[i] = col[i] = dri[i] = cig[i] = pet[i] = unknown;
    
      nat[0] = "Russian";
      col[1] = "Blue";
      dri[2] = "Milk";
    
      CheckAll (i1,  nat,"Englishman",  col,"Red")
      CheckAll (i2,  nat,"Italian",     dri,"Tea")
      CheckAll (i3,  nat,"Japanese",    cig,"Assos")
      CheckAll (i4,  nat,"Spanish",     pet,"Dog")
      CheckAll (i5,  col,"Green",       dri,"Coffee")
      CheckDist(i6,  i5,1,              col,"Grey")
      CheckAll (i7,  cig,"Kent",        col,"Yellow")
      CheckDist(i8,  i7,1,              pet,"Horse")
      CheckAll (i9,  cig,"Marlboro",    cig,"Marlboro")
      CheckDist(i10, i9,1,              pet,"Fox")
      CheckAll (i11, dri,"Juice",       cig,"Pall Mall")
      CheckAll (i12, pet,"Snake",       cig,"Camel")
      CheckAll (i13, pet,"Cat",         pet,"Cat")
      CheckDist(i14, i13,4,             dri,"Vodka")
      
      printf("--------\n");
      for(i=0; i<5; i++) {
        printf("%-10s  %-6s  %-6s  %-9s  %-5s\n",
               nat[i], col[i], dri[i], cig[i], pet[i]);
      }
    
      EndCheck() EndCheck() EndCheck() EndCheck() EndCheck()
      EndCheck() EndCheck() EndCheck() EndCheck() EndCheck()
      EndCheck() EndCheck() EndCheck() EndCheck() 
      return 0;
    }
    
    I won't take responsibillity for the humiliation you'll be put to if you use that coding style. For instance, writing unbalanced gull-wings in macros is something that warrants a serious slapping with a dead trout. But hey, it made it easy to write it. :D

    Btw, Simon what was your approach?

    [Edit]
    Removed some unnecessary stuff in the code.
     
  4. TekkenMaster

    Newcomer

    Joined:
    Feb 17, 2005
    Messages:
    70
    Likes Received:
    1
    Code:
    #include <stdio.h>
    
    /*
      Russian      leftmost
      Russian   +- blue 
      milk         middle
    
      Englishman   red 
      Italian      tea
      Japanese     Assos
      Spanish      dog
    
      green        coffee
      green     +- grey        // "near"
    
      Kent         yellow
      Kent      +- horse
    
      Marlboro  +- fox
      juice        Pall Mall
      snake        Camel
      cat      +-4 vodka       // "lateral"
    */
    
    char* sNat[6] = {"Englishman", "Italian", "Russian", "Japanese", "Spanish", "?"};
    char* sCol[6] = {"Red", "Green", "Yellow", "Blue", "grey", "?"};
    char* sDri[6] = {"Coffee", "Tea", "Milk", "Juice", "Vodka", "?"};
    char* sCig[6] = {"Kent", "Marlboro", "Pall Mall", "Assos", "Camel", "?"};
    char* sPet[6] = {"Fox", "Horse", "Dog", "Snake", "Cat", "?"};
    
    enum {Englishman, Italian, Russian, Japanese, Spanish};
    enum {Red, Green, Yellow, Blue, Grey};
    enum {Coffee, Tea, Milk, Juice, Vodka};
    enum {Kent, Marlboro, Pall_Mall, Assos, Camel};
    enum {Fox, Horse, Dog, Snake, Cat};
    
    #define unknown (5)
    #define Known(X) (X!=unknown)
    
    #define FOR(I)   for(I=0;I<5;I++)
    
    #define CheckAll(I, P1, V1, P2, V2) \
      FOR(I) {\
        int *p1=&P1[I], *p2=&P2[I];\
        if(Known(*p1)) continue; \
        if(Known(*p2)) continue; \
        *p1=V1; *p2=V2;
    
    #define CheckDist(I, I0, D, P1, V1) \
      for(I=I0-D;I<=I0+D;I+=2*D) {\
        int *p1=&P1[I], *p2=&P1[I];\
        if(I<0 || I>4) continue; \
        if(Known(*p1)) continue; \
        *p1=V1;
    
    #define EndCheck() \
      *p1 = *p2 = unknown; }
    
    int main(int argc, char* argv[])
    {
      int i;
      int i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14;
      int nat[5], col[5], dri[5], cig[5], pet[5];
    
      FOR(i) { nat[i] = col[i] = dri[i] = cig[i] = pet[i] = unknown; }
    
      nat[0] = Russian;
      col[1] = Blue;
      dri[2] = Milk;
    
      CheckAll (i1,  nat,Englishman,  col,Red)
      CheckAll (i2,  nat,Italian,     dri,Tea)
      CheckAll (i3,  nat,Japanese,    cig,Assos)
      CheckAll (i4,  nat,Spanish,     pet,Dog)
      CheckAll (i5,  col,Green,       dri,Coffee)
      CheckDist(i6,  i5,1,            col,Grey)
      CheckAll (i7,  cig,Kent,        col,Yellow)
      CheckDist(i8,  i7,1,            pet,Horse)
      CheckAll (i9,  cig,Marlboro,    cig,Marlboro)
      CheckDist(i10, i9,1,            pet,Fox)
      CheckAll (i11, dri,Juice,       cig,Pall_Mall)
      CheckAll (i12, pet,Snake,       cig,Camel)
      CheckAll (i13, pet,Cat,         pet,Cat)
      CheckDist(i14, i13,4,           dri,Vodka)
     
      printf("--------\n");
      FOR(i) {
        //printf("%d  %d  %d  %d  %d    ", nat[i], col[i], dri[i], cig[i], pet[i]);
        printf("%-10s  %-6s  %-6s  %-9s  %-5s\n",
               sNat[nat[i]],
               sCol[col[i]],
               sDri[dri[i]],
               sCig[cig[i]],
               sPet[pet[i]]);
      }
    
      EndCheck() EndCheck() EndCheck() EndCheck()
      EndCheck() EndCheck() EndCheck() EndCheck()
      EndCheck() EndCheck() EndCheck() EndCheck()
      EndCheck() EndCheck()
      return 0;
    }
    Why is the solution more difficult than the question?
     
  5. K.I.L.E.R

    K.I.L.E.R Retarded moron
    Veteran

    Joined:
    Jun 17, 2002
    Messages:
    2,952
    Likes Received:
    50
    Location:
    Australia, Melbourne
    Seconded.
    Someone needs to go back to the future.
    :lol:
     
  6. pcchen

    pcchen Moderator
    Moderator Veteran Subscriber

    Joined:
    Feb 6, 2002
    Messages:
    3,018
    Likes Received:
    582
    Location:
    Taiwan
    Actually it's not :)

    I also cheated once for a puzzle, it's also an old one. I don't remember the exact numbers, but it's about several people crossing a bridge at night. There are only one lamp and the bridge is so small, so there can be only two people crossing the bridge at once, and one person must come back to bring the lamp for others. The walking speed of those people are all different, and you have to make all four persons cross the bridge under a specific time. When two people walking across the bridge, the faster one must slows down to match the slow one. And they are all fat, so they can't go on each other's back :)

    In one example, the speeds are: 1 minutes (to cross the bridge), 2 minutes, 5 minutes, and 6 minutes. The time requirement is 13 minutes. It's different from the numbers in the puzzle I saw, but the idea is the same.

    When I saw that puzzle, I tried for several minutes and got impatient, so I wrote a small C program to solve it. When I saw the answer the program produced, I thought "Ah! Of course!" That's one of a few moment when I think computer is smarter than I :p
     
  7. K.I.L.E.R

    K.I.L.E.R Retarded moron
    Veteran

    Joined:
    Jun 17, 2002
    Messages:
    2,952
    Likes Received:
    50
    Location:
    Australia, Melbourne
    IMO ASM is far cleaner than C.

    I honestly don't know why people don't just go back to ASM.
     
  8. Basic

    Regular

    Joined:
    Feb 8, 2002
    Messages:
    846
    Likes Received:
    13
    Location:
    Linköping, Sweden
    The C code includes both the question and a explicit method to solve it, of course it's longer than just the question written in english. I suppose you dont know C, so of course it will also look more difficult, since it's written in a language you don't know.

    [Edit]
    I'm sorry, that might have sounded condescending, and I didn't mean to.
    And now I see that I used one unnecessary indirection level in the code. I'll change that above.
     
  9. TekkenMaster

    Newcomer

    Joined:
    Feb 17, 2005
    Messages:
    70
    Likes Received:
    1
    Wrong presupposition.

    Wasn't aware Courier New has become a standard font for writing codes, but if it means you'll stop lamenting like your Xbox power cord was set ablazed, I've taken the time and effort to review and edit my previous post.
     
  10. Basic

    Regular

    Joined:
    Feb 8, 2002
    Messages:
    846
    Likes Received:
    13
    Location:
    Linköping, Sweden
    Oops, I didn't edit that quick enough.

    I removed my request for code-tags when I saw that you put them there. It was certainly not ment like you bold-faced it. It was meant as a polite request.

    Courier New might not be standard, but using a non-proportional font definitely is.

    The reason I thought you didn't know C, was that if you'd been programming you wouldn't ask that question. You'd know the answer already.
     
  11. Crisidelm

    Newcomer

    Joined:
    May 25, 2004
    Messages:
    9
    Likes Received:
    4
    yes, I do think so, then again, was Einstein wrong about the 2%? Probably so, but who knows. Definitively there are people who can solve it mentally, how many, I don't know. I'm not one of them for sure :)
     
  12. Simon F

    Simon F Tea maker
    Moderator Veteran

    Joined:
    Feb 8, 2002
    Messages:
    4,563
    Likes Received:
    171
    Location:
    In the Island of Sodor, where the steam trains lie
    The approach I took is the same way I solve them by hand (more or less). You have a big grid of possibilities (i.e. potential facts) and immediately mark in those permitted by the rules and those that are ruled-out. This then reveals new facts (which can cancel out other possibilities). You keep going until the solution is left.

    This particular puzzle differs from many that are published in that there is a fair amount of "implicit" information in the facts.



    Well, before releasing the code, I was thinking about making it more generic so that it could "parse" a problem file rather than having the conditions hardwired in, but I guess I'm not going to get time to do that : -)

    BTW: This is hacked code, so it's not very pretty.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    /*
    // Define the number of elements
    */
    #define NUM_ITEMS (5)
    
    /*
    // Define the number of properties each item has
    */
    #define NUM_PROPERTIES (6)
    
    /*
    // Define the names of the properties
    */
    const char * PropertyTypes[NUM_PROPERTIES] =
    {
    	"number",
    	"colour",
    	"nationality",
    	"drink",
    	"cigar",
    	"pet"
    };
    /*
    // For convience, also give these numeric codes
    */
    enum
    {
    	NUMBERS,
    	COLOURS,
    	NATIONALITY,
    	DRINKS,
    	CIGARS,
    	PETS
    } Properties;
    
    /*
    // Define all the things (they must be unique).
    // They can be in any order (as long as they are grouped correctly!)
    // (well the house numbers should be in the correct order!)
    */
    const char *Everything[NUM_PROPERTIES * NUM_ITEMS]=
    {
    		"house 1",
    		"house 2",
    		"house 3",
    		"house 4",
    		"house 5",
    
    		"red",
    		"green",
    		"blue",
    		"white",
    		"yellow",
    
    
    		"swede",
    		"brit",
    		"dane",
    		"norwegian",
    		"german",
    
    
    		"tea",
    		"coffee",
    		"milk",
    		"beer",
    		"water",		
    
    
    		"dunhill",
    		"blend",
    		"bluemaster",
    		"prince",
    		"pallmall",
    
    		"dogs",
    		"cats",
    		"horse",
    		"birds",
    		"fish",
    };
    
    
    /*
    // Define the way we represent facts
    */
    #define YES (1)
    #define NO	(-1)
    #define NOT_DECIDED (-2)
    
    /*
    // Define a big array containing all the known facts
    // (note there is redundacy, but it makes it much easier to program)
    */
    int Facts[NUM_PROPERTIES * NUM_ITEMS][NUM_PROPERTIES * NUM_ITEMS];
    
    /*
    // Routines
    */
    static void InitialiseFacts();
    
    static void AddTheSame(char const *Item1, char const *Item2);
    
    static void AddNotTheSame(char const *Item1, char const *Item2, int verbose);
    
    /*
    // Search for a new fact as revealed by a process of elimination.
    // return non-zero if a new fact was found.
    */
    static int DoNewFactSearch(char const **NewEquiv1, char const **NewEquiv2);
    
    
    /*
    // Asks if we know what is what. Returns a NON zero value (and the index for 
    // the string) if we know.
    */
    static int WhatIs(char const *Item, 
    				  char const *AskedProperty, 
    				  int *EquivalentIndex);
    
    
    /*
    // returns TRUE if we know for certain that Item1 != Item2
    */
    static int DefinitelyNot(char const *Item1, char const *Item2);
    
    
    /*
    // Bit of a special routine for this puzzle
    // 
    */
    static void AddNeighbours(char const *Item1, char const *Item2);
    
    
    
    /*
    // main routine
    */
    void main(void)
    {
    	int answer, Index, i;
    	char const *NewFact1,  *NewFact2;
    
    	/*
    	// Intialise the facts structure
    	*/
    	InitialiseFacts();
    
    
    	/*
    	// Add all the basic, really straightforward facts
    	*/
    	AddTheSame("brit", "red");
    	AddTheSame("swede", "dogs");
    	AddTheSame("dane", "tea");
    
    	AddNotTheSame("green", "house 5", 1);
    	AddNotTheSame("white", "house 1", 1);
    
    	AddTheSame("green", "coffee");
    	AddTheSame("pallmall", "birds");
    	AddTheSame("yellow", "dunhill");
    
    	AddTheSame("house 3", "milk");
    	AddTheSame("norwegian", "house 1");
    
    	AddNotTheSame("blend", "cats",    1);
    	AddNotTheSame("horse", "dunhill", 1);
    
    	AddTheSame("bluemaster", "beer");
    	AddTheSame("german", "prince");
    	
    	AddNotTheSame("norwegian", "blue", 1);
    	AddNotTheSame("blend", "water",    1);
    
    
    	printf("Added initial,  easy facts.......\n\n");
    
    	/*
    	// keep looping until we know who the hell owns the fish :-)
    	*/
    	while(WhatIs("fish", "nationality", &answer) == 0)
    	{
    		/*		
    		// Cross reference all the facts we've got so far.
    		*/
    		printf("\nDoing Elimination Search....\n");
    		while(DoNewFactSearch(&NewFact1, &NewFact2))
    		{
    			printf("Discovered that %s == %s\n", NewFact1, NewFact2);
    
    			AddTheSame(NewFact1, NewFact2);
    
    			printf("\n");
    		}
    		printf("\n");
    
    
    		/*
    		// Do the tricky rules.
    		//
    		// Add the less precise neighbour information
    		*/
    		AddNeighbours("blend", "cats");
    		AddNeighbours("horse", "dunhill");
    		AddNeighbours("norwegian", "blue");
    		AddNeighbours("blend", "water");
    
    
    		
    		/*
    		// Now for the nasty one.
    		//
    		//    green to left of white
    		//
    		// if we know green's number AND white's number, then don't bother
    		*/
    		if( WhatIs("green", "number", &Index) && 
    			WhatIs("white", "number", &Index))
    		{
    			/*do nothing more*/
    		}
    		/*
    		// Else if we know where at least one of them is...
    		*/
    		else if( WhatIs("green", "number", &Index))
    		{
    			AddTheSame("white", Everything[Index+1]);
    		}
    		else if(WhatIs("white", "number", &Index))
    		{
    			AddTheSame("green", Everything[Index-1]);
    		}
    		/*
    		// else we don't know which is which but...
    		//
    		//  if we know green is NOT house N, then white is NOT house N+1
    		*/
    		else
    		{
    			/*
    			// step through the possible houses
    			*/
    			for(i = 0; i < 4; i++)
    			{
    				if(DefinitelyNot("green", Everything[i+ NUMBERS* NUM_ITEMS]))
    				{
    					AddNotTheSame("white", 
    								 Everything[i+1+NUMBERS* NUM_ITEMS], 0);
    				}
    			}
    			for(i = 1; i < 5; i++)
    			{
    				if(DefinitelyNot("white", Everything[i+ NUMBERS* NUM_ITEMS]))
    				{
    					AddNotTheSame("green", 
    								  Everything[i-1+NUMBERS* NUM_ITEMS], 0);
    				}
    			}
    		}/*end else... handling green and white*/
    
    
    	}
    	printf("\n\nThe fish is owned by the %s\n", Everything[answer]);
    	
    }
    
    
    
    /******************************************************************/
    /******************************************************************/
    /******************************************************************/
    /* The guts......*/
    
    static void AddNeighbours(const char *Item1, const char *Item2)
    {
    	int Index;
    	int ThisHouse;
    	int i;
    
    
    	/*
    	// If we already know where both houses are, then just do a sanity
    	// check
    	*/
    	if(WhatIs(Item1, "number", &Index) && WhatIs(Item2, "number", &i))
    	{
    		if(abs(Index - i) != 1)
    		{
    			printf("Error %s and %s are supposed to be neighbours!\n",
    						  Item1, Item2);
    
    			exit(1);
    		}
    
    
    		return;
    
    	}
    
    	printf("Trying to add %s and %s as neighbours.. \n", Item1, Item2);
    
    	/*
    	// If we know Item1's number...
    	*/
    	if(WhatIs(Item1, "number", &Index))
    	{
    		/*
    		// mark any houses that are not neighbours
    		*/
    		for(i = 0; i < 5; i++)
    		{
    			ThisHouse = i+NUMBERS*NUM_ITEMS;
    	
    			/*
    			// if this house is not a neighbour
    			*/
    			if((ThisHouse != Index-1) && (ThisHouse != Index+1))
    			{
    				AddNotTheSame(Item2, Everything[ThisHouse], 0);
    			}
    		}
    	}
    	else if(WhatIs(Item2, "number", &Index))
    	{
    		/*
    		// mark any houses that are not neighbours
    		*/
    		for(i = 0; i < 5; i++)
    		{
    			ThisHouse = i+NUMBERS*NUM_ITEMS;
    	
    			/*
    			// if this house is not a neighbour
    			*/
    			if((ThisHouse != Index-1) && (ThisHouse != Index+1))
    			{
    				AddNotTheSame(Item1, Everything[ThisHouse], 0);
    			}
    		}
    	}
    }
    
    /******************************************************************/
    /******************************************************************/
    /******************************************************************/
    
    static void InitialiseFacts()
    {
    	int i, j, k;
    	int Base;
    	/*
    	// Clear everything out
    	*/
    	for(i = 0; i < NUM_ITEMS * NUM_PROPERTIES; i++)
    	{
    		for(j = 0; j < NUM_ITEMS * NUM_PROPERTIES; j++)
    		{
    			Facts[i][j] = NOT_DECIDED;
    		}
    	}
    	/*
    	// Now put in the "bleeding obvious... i.e. X==X
    	*/
    	for(k = 0; k < NUM_PROPERTIES; k++)
    	{
    		Base = k * NUM_ITEMS;
    
    		for(i = 0; i < NUM_ITEMS; i++)
    		{
    			for(j = 0; j < NUM_ITEMS; j++)
    			{
    				Facts[Base+i][Base+j] = NO;
    			}
    
    			/*
    			// Just fix the main diagonal i.e. X==X
    			*/
    			Facts[Base+i][Base+i] = YES;
    		}
    	}
    }
    
    
    static void AddTheSame(char const *Item1, char const *Item2)
    {
    	int Index1, Index2;
    	int i;
    
    	printf("Adding %s == %s \n", Item1, Item2);
    	/*
    	// Find the two items
    	*/
    	for(Index1 = 0; Index1 < NUM_PROPERTIES * NUM_ITEMS; Index1++)
    	{
    		if(strcmp(Everything[Index1], Item1) == 0)
    		{
    			break;
    		}
    	}
    	if(Index1 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddTheSame(%s, %s)\n",
    						Item1,  Item1, Item2);
    
    		exit(1);
    	}
    
    	for(Index2 = 0; Index2 < NUM_PROPERTIES * NUM_ITEMS; Index2++)
    	{
    		if(strcmp(Everything[Index2], Item2) == 0)
    		{
    			break;
    		}
    	}
    	if(Index2 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddTheSame(%s, %s)\n",
    						Item2,  Item1, Item2);
    		exit(1);
    	}
    
    
    	/*
    	// fill in the details: Cross reference the information
    	// These two items are identical, and so each can share the other's
    	// information.
    	*/
    	for(i = 0; i < NUM_PROPERTIES * NUM_ITEMS; i++)
    	{
    		/*
    		// Do rows
    		*/
    		if( (Facts[Index1][i] == NO) || (Facts[Index2][i] == NO))
    		{
    			/*
    			//Do a sanity check
    			*/
    			if((Facts[Index1][i] == YES) || (Facts[Index2][i] == YES))
    			{
    				printf("Error. %s and %s disagree about %s!\n",
    						Item1,  Item2, Everything[i]);
    			}
    
    			/*
    			// Update the info
    			*/
    			Facts[Index1][i] = NO;
    			Facts[Index2][i] = NO;
    		}/*end if*/
    
    #if 0
    		else if( (Facts[Index1][i] == YES) || (Facts[Index2][i] == YES))
    		{
    			/*
    			// Update the info
    			*/
    			Facts[Index1][i] = YES;
    			Facts[Index2][i] = YES;
    		}
    #endif
    		/*
    		// Do columns
    		*/
    		if( (Facts[i][Index1] == NO) || (Facts[i][Index2] == NO) )
    		{
    			/*
    			//Do a sanity check
    			*/
    			if((Facts[i][Index1] == YES) || (Facts[i][Index2] == YES))
    			{
    				printf( "Error. %s and %s disagree about %s!\n",
    						Item1,  Item2, Everything[i]);
    			}
    
    			/*
    			// Update the info
    			*/
    			Facts[i][Index1] = NO;
    			Facts[i][Index2] = NO;
    		}
    #if 0
    		else if( (Facts[i][Index1] == YES) || (Facts[i][Index2] == YES))
    		{
    			/*
    			// Update the info
    			*/
    			Facts[i][Index1] = YES;
    			Facts[i][Index2] = YES;
    		}
    #endif
    
    	}/*end for*/
    
    
    	Facts[Index1][Index2] = YES;
    	Facts[Index2][Index1] = YES;
    }
    
    
    static void AddNotTheSame(char const *Item1, char const *Item2, int Verbose)
    {
    	int Index1, Index2;
    
    	if(Verbose)
    	{
    		printf("Adding %s != %s \n", Item1, Item2);
    	}
    	/*
    	// Find the two items
    	*/
    	for(Index1 = 0; Index1 < NUM_PROPERTIES * NUM_ITEMS; Index1++)
    	{
    		if(strcmp(Everything[Index1], Item1) == 0)
    		{
    			break;
    		}
    	}
    	if(Index1 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddNotTheSame(%s, %s)\n",
    						Item1,  Item1, Item2);
    
    		exit(1);
    	}
    
    	for(Index2 = 0; Index2 < NUM_PROPERTIES * NUM_ITEMS; Index2++)
    	{
    		if(strcmp(Everything[Index2], Item2) == 0)
    		{
    			break;
    		}
    	}
    	if(Index2 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddNotTheSame(%s, %s)\n",
    						Item2,  Item1, Item2);
    		exit(1);
    	}
    
    	/*
    	// Do a quick sanity check
    	*/
    	if((Facts[Index1][Index2] == YES) || (Facts[Index2][Index1] == YES))
    	{
    		printf("Error. %s and %s are supposed to be the same!\n",
    						Item1,  Item2);
    		exit(1);
    	}
    
    	/*
    	// fill in the details
    	*/
    	Facts[Index1][Index2] = NO;
    	Facts[Index2][Index1] = NO;
    }
    
    
    
    static int DefinitelyNot(char const *Item1, char const *Item2)
    {
    	int Index1, Index2;
    
    	/*
    	// Find the two items
    	*/
    	for(Index1 = 0; Index1 < NUM_PROPERTIES * NUM_ITEMS; Index1++)
    	{
    		if(strcmp(Everything[Index1], Item1) == 0)
    		{
    			break;
    		}
    	}
    	if(Index1 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddNotTheSame(%s, %s)\n",
    						Item1,  Item1, Item2);
    
    		exit(1);
    	}
    
    	for(Index2 = 0; Index2 < NUM_PROPERTIES * NUM_ITEMS; Index2++)
    	{
    		if(strcmp(Everything[Index2], Item2) == 0)
    		{
    			break;
    		}
    	}
    	if(Index2 == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		printf("Error. Couldn't find %s in AddNotTheSame(%s, %s)\n",
    						Item2,  Item1, Item2);
    		exit(1);
    	}
    
    
    	return(Facts[Index1][Index2] == NO);
    }
    
    
    
    /*
    // Search for new facts.
    // return non-zero if a new fact was found.
    */
    static int DoNewFactSearch(char const **NewEquiv1, char const **NewEquiv2)
    {
    	int RowToCheck, Property, i;
    	int NoCount, UnknownCount, YesCount;
    	int Base;
    	int LastUnknown;
    
    	for(RowToCheck = 0; RowToCheck < NUM_PROPERTIES * NUM_ITEMS; RowToCheck++)
    	{
    		/*
    		// Scan through it in blocks of properties. If we find that all
    		// bar one is set as NO, then it's a new fact
    		*/
    		for(Property = 0; Property < NUM_PROPERTIES; Property++)
    		{
    			Base = Property * NUM_ITEMS;
    			NoCount = 0;
    			YesCount= 0;
    			UnknownCount = 0;
    
    			for(i = 0; i < NUM_ITEMS; i++)
    			{
    				if(Facts[RowToCheck][i+Base] == NO)
    				{
    					NoCount++;
    				}
    				else if(Facts[RowToCheck][i+Base] == YES)
    				{
    					YesCount++;
    				}
    				else if(Facts[RowToCheck][i+Base] == NOT_DECIDED)
    				{
    					UnknownCount++;
    
    					LastUnknown = i+Base;
    				}
    			}/*end for i*/
    
    
    			/*
    			// If there is only one possibility left
    			*/
    			if((UnknownCount == 1) && (NoCount == (NUM_ITEMS-1)))
    			{
    
    				*NewEquiv1 = Everything[RowToCheck];
    				*NewEquiv2 = Everything[LastUnknown];
    
    				return 1;
    			}
    			/*
    			// Else do some sanity checks...
    			*/
    			else if(NoCount == NUM_ITEMS)
    			{
    				printf("Error. %s doesn't have a %s available!\n",
    						Everything[RowToCheck], PropertyTypes[Property]);
    				exit(1);
    			}
    			else if(YesCount > 1)
    			{
    				printf("Error. %s IS MAPPED TO TWO %s !!!\n",
    						Everything[RowToCheck], PropertyTypes[Property]);
    				exit(1);
    			}
    			else if(UnknownCount + YesCount + NoCount != NUM_ITEMS)
    			{
    				printf("Error. %s has error in %s (%d %d %d)!!!\n",
    						Everything[RowToCheck], PropertyTypes[Property],
    						UnknownCount, YesCount, NoCount);
    				exit(1);
    			}
    		}
    	}
    
    	/*
    	// no luck
    	*/
    	return 0;
    }
    
    
    
    /*
    // Asks if we know what is what. Returns a NON zero value (and the index for 
    // the string) if we know.
    */
    static int WhatIs(char const *Item, 
    				  char const *AskedProperty, 
    				  int *pEquivalentIndex)
    {
    	int Index, Property;
    	int i;
    	int Base;
    
    	/*
    	// Find the item
    	*/
    	for(Index = 0; Index < NUM_PROPERTIES * NUM_ITEMS; Index++)
    	{
    		if(strcmp(Everything[Index], Item) == 0)
    		{
    			break;
    		}
    	}
    
    	if(Index == NUM_PROPERTIES * NUM_ITEMS)
    	{
    		fprintf(stderr, "Error. Couldn't find %s in Whatis(%s, %s)\n",
    						Item,  Item, AskedProperty);
    
    		exit(1);
    	}
    
    	/*
    	// Find the property
    	*/
    	for(Property = 0; Property < NUM_PROPERTIES;  Property++)
    	{
    		if(strcmp(PropertyTypes[Property], AskedProperty) == 0)
    		{
    			break;
    		}
    	}
    
    	if(Property == NUM_PROPERTIES)
    	{
    		fprintf(stderr, "Error. Couldn't find %s in Whatis(%s, %s)\n",
    						AskedProperty,  Item, AskedProperty);
    
    		exit(1);
    	}
    
    	/*
    	// Search through the area looking for a yes
    	*/
    	Base = Property * NUM_ITEMS;
    
    	for(i = Base; i < Base + NUM_ITEMS; i++)
    	{
    		if(Facts[Index][i] == YES)
    		{					
    			*pEquivalentIndex = i;
    			return 1;
    		}
    	}
    	
    	/*
    	// Else no luck
    	*/
    	*pEquivalentIndex = -100000;
    	return 0;
    
    }
    
    /*
    // END OF FILE
    */
    
    
     
  13. pat777

    Newcomer

    Joined:
    May 19, 2004
    Messages:
    230
    Likes Received:
    0
    I didn't get it, but I got close. Then I read the answers :( When I saw the flash movie, I did see the "hypotenuse" bend. The "hypotenuse" doesn't look exactly the same in those 2 pictures. I couldn't figure out why, until I read the answer. :(
     
Loading...

Share This Page

  • About Us

    Beyond3D has been around for over a decade and prides itself on being the best place on the web for in-depth, technically-driven discussion and analysis of 3D graphics hardware. If you love pixels and transistors, you've come to the right place!

    Beyond3D is proudly published by GPU Tools Ltd.
Loading...