#include <stdio.h>

#define PEGNUM 4
#define COLORNUM 6
struct Attempt
{
  char guess[PEGNUM];
  int black;
  int white;
};

void
Attempt_print(struct Attempt *pA)
{
  printf("%4.4s\n%d\n%d\n", pA->guess, pA->black, pA->white);
}

void
copyCombo (char *src, char *dest)
{
  int i;

  for (i = 0; i < PEGNUM; ++i)
    {
      *dest = *src;
      dest = dest + 1;
      src = src + 1;
    }
}

void
Attempt_score (struct Attempt *pAttempt, char trueCombo[4])
{
  char copyOfTrueCombo[PEGNUM];
  char copyOfGuess[PEGNUM];
  int i;
  int j;

  pAttempt->white = 0;
  pAttempt->black = 0;
  copyCombo (trueCombo, copyOfTrueCombo);
  copyCombo (pAttempt->guess, copyOfGuess);
  for (i = 0; i < PEGNUM; ++i)
    {
      if (copyOfTrueCombo[i] == copyOfGuess[i])
	{
	  pAttempt->black += 1;
	  copyOfTrueCombo[i] = '0' + COLORNUM;
	  copyOfGuess[i] = '0' + COLORNUM + 1;
	}
    }
  for (i = 0; i < PEGNUM; ++i)
    {
      for (j = 0; j < PEGNUM; ++j)
	{
	  if (copyOfTrueCombo[i] == copyOfGuess[j])
	    {
	      pAttempt->white += 1;
	      copyOfTrueCombo[i] = '0' + COLORNUM;
	      copyOfGuess[j] = '0' + COLORNUM + 1;
	    }
	}
    }
}

#define MAXGUESS 10

struct Guesses
{
  int num;
  struct Attempt guesses[MAXGUESS];
};

int
check (char combo[PEGNUM], struct Attempt *pAttempt)
{
  struct Attempt sim;

  copyCombo ((char*)&pAttempt->guess, (char*)&sim.guess);
  Attempt_score (&sim, combo);
  if (sim.black == pAttempt->black && sim.white == pAttempt->white)
    {
      return 1;
    }
  else
    {
      return 0;
    }
}

int
isconsistent (struct Guesses * pGuesses)
{
  int j;
  int b;

  j = pGuesses->num;
  b = 1;
  while (j > 0 && b != 0)
    {
      j = j - 1;
      b =
	check (pGuesses->guesses[pGuesses->num].guess,
	       &pGuesses->guesses[j]);
    }
  return b;
}

int
gentest (struct Guesses *pGuesses, int pos)
{
  if (pos >= PEGNUM)
    {
      return isconsistent (pGuesses);
    }
  else
    {
      char *pCh;
      int b;
      b = 0;
      pCh = &pGuesses->guesses[pGuesses->num].guess[pos];
      *pCh = '0' - 1;
      while (!b && (*pCh <= ('0' + COLORNUM - 2)))
	{
	  ++(*pCh);
	  b = gentest (pGuesses, pos + 1);
	}
      return b;
    }
}

int
readdec (int *pInt)
{
  int numread;
  int value;
  char ch;

  numread = 0;
  value = 0;
  do
    {
      numread = read (0, &ch, 1);
      if (numread != 0 && ch != '\n')
	{
	  value = value * 10 + (ch - '0');
	}
    }
  while (numread != 0 && ch != '\n');
  *pInt = value;
  return numread;
}

int
main (void)
{
  struct Guesses guesses;
  int b;
  int done;

  guesses.num = 0;
  b = 0;
  done = 0;
  do
    {
      guesses.guesses[guesses.num].black = 0;
      guesses.guesses[guesses.num].white = 0;
      b = gentest (&guesses, 0);
      if (b)
	{
	  Attempt_print (&guesses.guesses[guesses.num]);
	  readdec (&guesses.guesses[guesses.num].black);
	  readdec (&guesses.guesses[guesses.num].white);
	  done = guesses.guesses[guesses.num].black == PEGNUM;
	  ++guesses.num;
	}
    }
  while (b && !done);
  if (!b)
  {
    printf("you cheated!\n");
  }
}

