Puzzle

My little detective

A.The problem:

The police have three suspects for the murder of Mr Cooper: Mr Smith, Mr
Jones, and Mr Williams.

Smith, Jones, and Williams each declare that they did not kill Cooper.
Smith also states that Cooper was a friend of Jones and that Williams
disliked him.
Jones also states that he did not know Cooper and that he was out of
town the day Cooper was killed.
Williams also states that he saw both Smith and Jones with Cooper the
day of the killing and that either Smith or Jones must have killed him.
Can you determine who the murderer was if

i) one of the three men is guilty, the two innocent men are telling the truth,
but the statements of the guilty man may or may not be true?
ii) innocent men do not lie?

    B.First Edition

    This is the first edition of this simple "detective" program. As the situation is rather straight forward, it

    saves me a lot of trouble and I even don't bother to try to design it as a certain class for re_usable which I

    am highly doubtful.

    1¡£ Basic idea: This program estabish a big facts Matrix according to each suspect's statement. In the matrix,

    	I listed each suspect about a certain fact involving other suspect(s). In order to detect which suspect

    	had given an opinion to a certain fact which is always different or conflict with all other suspect, we

    	can determine who is the murderer, basing the idea that only one murderer is involved and only he lies.

    	However, this fact sheet may not work if a certain fact opinion is uncertain. For example, if a suspect

    	states that either suspect A or suspect B does a certain thing, then in my matrix, it is hard to express

    	this idea. I have not figured out about this kind of situations.

    2¡£ Program design: With a 3-subscript array, I can store all facts---int Facts[FactNum][PeopleNum][PeopleNum].

    	first column is the fact, second is the opinion given from, the third is the suspect involved in fact

    	statement. And with a 2-subscript, I can store the conflict----int Conflict[PeopleNum][PeopleNum].

    3¡£ Major function£º

         A.  void analysis();

    	It uses a internal method: void checkAgree(int opFrom, int opTo, int factTable[PeopleNum][PeopleNum]);

    	to write conflicts data into conflict table, based on the idea that if one suspect has different opinion with any

    	other suspect.

    4¡£ Further improvement£º

    	A. I write it for fun with a couple of hours and didn't want to write complicated analysis functions.

    	It is extremely trivial and simple, so I am not interested in improving it.

    	B. I have to re-write "my detective" case by case as determine "facts" is a hard job by analysis with

    	programmer. (I also wrote a Logic class but stucked with how to store relations with facts.)

    	C. For simple judgement of who is murderer, I have to say it is too simple as there will be only one

    	real murderer and only he gives lies. Suppose there is uncertain number of murderer, it is hard to

    	determine who is lying and...

    #include <iostream>

    using namespace std;

    const PeopleNum =3;

    const FactNum = 4;

    enum Suspect {Smith, Jones, Williams};

    enum Fact {Killer, Friend, Acquaintance, Stay};

    enum Status {Positive=1, Undefined=0, Negative=-1};

    char* nameStr[PeopleNum] = {"Smith", "Jones", "Willia"};

    char* factStr[FactNum] = {"Opinion of killer", "Opinion of friend relation with the dead",
    "Opinion of acquaintance with the dead", "Opinion of staying with the dead"};

    char* conflictStr[2] = {"Agree", "Confli"};

    int Facts[FactNum][PeopleNum][PeopleNum] = {0}; //the fact matrix

    int Conflict[PeopleNum][PeopleNum] = {0};

    void initialize();

    void displayFact();

    void analysis();

    void displayConflict();

    void simpleJudge();

    int main()
    {
    	initialize();
    	displayFact();
    	analysis();
    	displayConflict();
    	simpleJudge();

    	return 0;
    }

    void initialize()
    {
    	//three suspect all denies himself to be killer
    	for (int i=0; i< PeopleNum; i++)
    	{
    		Facts[Killer][i][i] = Negative;
    	}

    	//smith statement: Jones&Williams both know the dead
    	Facts[Friend][Smith][Jones] = Positive;//Jones is friend of Cooper
    	Facts[Friend][Smith][Williams] = Negative;//Williams dislike Cooper
    	Facts[Acquaintance][Smith][Jones] = Positive;//Jones is friend of Cooper
    	Facts[Acquaintance][Smith][Williams] = Positive;//Williams dislike Cooper

    	//Jones statements
    	Facts[Friend][Jones][Jones] = Negative; //he didnot know the dead
    	Facts[Acquaintance][Jones][Jones] = Negative;//he didnot know the dead
    	Facts[Stay][Jones][Jones] = Negative;//Jones said he was out of town

    	//Williams statement
    	Facts[Stay][Williams][Jones] = Positive;//he saw Jones with Cooper
    	Facts[Stay][Williams][Smith] = Positive;//he saw Williams with Cooper
    }

    void displayFact()
    {
    	for (int i=0; i< FactNum; i++)
    	{
    		cout<<"\n"<<factStr[i]<<"\n";
    		cout<<"From:\tTo:\t";
    		for (int j=0; j< PeopleNum; j++)
    		{
    			cout<<nameStr[j]<<"\t";
    		}
    		cout<<"\n";
    		for (int suspect=0; suspect< PeopleNum; suspect++)
    		{
    			cout<<nameStr[suspect]<<"\t\t";
    			for (int fact=0; fact<PeopleNum; fact++)
    			{
    				cout<<Facts[i][suspect][fact]<<"\t";
    			}
    			cout<<"\n";
    		}
    		cout<<"\n";
    	}
    }

    void analysis()
    {
    	void checkAgree(int opFrom, int opTo, int factTable[PeopleNum][PeopleNum]);
    	for (int fact=0; fact< FactNum; fact++)
    	{
    		for (int opFrom=0; opFrom< PeopleNum; opFrom++)
    		{
    			for (int opTo =0; opTo< PeopleNum; opTo++)
    			{
    				if (Facts[fact][opFrom][opTo]!= Undefined)
    					checkAgree(opFrom, opTo, Facts[fact]);
    			}
    		}
    	}
    }

    void checkAgree(int opFrom, int opTo, int factTable[PeopleNum][PeopleNum])
    {

    	for (int suspect =0; suspect < PeopleNum; suspect++)
    	{
    		for (int opTarget =0; opTarget< PeopleNum; opTarget++)
    		{
    			if (suspect!=opFrom)
    			{
    				if (factTable[suspect][opTo]!=factTable[opFrom][opTo]&&
    					factTable[suspect][opTo]!=0)
    				{
    					Conflict[opFrom][suspect] = 1;
    					Conflict[suspect][opFrom] = 1;
    				}
    			}
    		}
    	}
    }

    void displayConflict()
    {
    	cout<<"\nNow display the conflict table\n";
    	cout<<"Suspect\tSuspect\t";
    	for (int suspect=0; suspect< PeopleNum; suspect++)
    	{
    		cout<<nameStr[suspect]<<"\t";
    	}
    	cout<<"\n";

    	for (int from=0; from< PeopleNum; from ++)
    	{

    		cout<<nameStr[from]<<"\t\t";
    		for (int to=0; to< PeopleNum; to++)
    		{
    			cout<<conflictStr[Conflict[from][to]]<<"\t";
    		}
    		cout<<"\n";
    	}
    }

    void simpleJudge()
    {
    	int result[PeopleNum] = {0};
    	for (int suspect=0; suspect< PeopleNum; suspect++)
    	{
    		for (int conflict=0; conflict< PeopleNum; conflict++)
    		{
    			result[suspect] += Conflict[suspect][conflict];
    		}
    		if (result[suspect]<=1)
    		{
    			cout<<"\n"<<nameStr[suspect]<<" is innocent!\n";
    		}
    		else
    		{
    			if (result[suspect]==PeopleNum-1)
    			{
    				cout<<"\n"<<nameStr[suspect]<<" is conflicting with every other people,";
    				cout<<"So, he is the murderer!\n";
    			}
    		}
    	}
    }

    The above result shows that: -1==Negative, 0==No opinion, 1==Positive

    ¡¡