#include <stdio.h>
#include <conio.h>

#define U0 325
#define K 100

/**************
*  QUESTION 1 *
***************/
int u(int N)
{
  static int n=0;
  static int u_n=U0;
  if (N<n)
  {
    n=0;
    u_n=U0;
  }
  for (;n<N;n++)
  {
    u_n*=16383;
    u_n%=59047;
  }
  return u_n;
}

void Question1()
{
  printf("1) u(996)=%i",u(996));
  printf(" u(9996)=%i\n",u(9996));  /* Sinon, les paramètres sont évaluées dans un ordre inconnu. */
}

/**************
*  QUESTION 2 *
***************/
int v(int i)
{
  int u_i=u(i);
  if (u_i%3==0)
    return 1;
  else
    return 0;
}

void Question2()
{
  int i;
  int n=10000;
  for (i=0;i<10000;i++)
    n-=v(i);
  printf("2) Nombre de v(i)=0 pour 0 <= i < 10000 : %i\n",n);
}

/**************
*  QUESTION 3 *
***************/
int CaseInitial(int i,int j)
{
  return v(i+K*j);
}

void Question3()
{
  printf("3) A t=0, la case de coordonnées (1,0) ");
  if (CaseInitial(1,0))
    printf("contient une cellule vivante.\n");
  else
    printf("est vide.\n");
}

/**************
*  QUESTION 4 *
***************/
#define S sizeof(int)
int tore[2][K*K/S+1];

void Set(int t,int i,int j)
{
  int o=i+K*j;
  int b=o%S;
  o/=S;
  tore[t%2][o]|=(1<<b);
}

void Clear(int t,int i,int j)
{
  int o=i+K*j;
  int b=o%S;
  o/=S;
  tore[t%2][o]&=0xFFFFFFFF-(1<<b);
}

int Read(int t,int i,int j)
{
  int o,b;
  if (i==-1)
    i=K-1;
  if (j==-1)
    j=K-1;
  if (i==K)
    i=0;
  if (j==K)
    j=0;
  o=i+K*j;
  b=o%S;
  o/=S;
  return (tore[t%2][o]&(1<<b))!=0;
}

/* Initialise le tore à t=0 */
void t_0()
{
  int i,j;
  for (j=0;j<K;j++)
    for (i=0;i<K;i++)
      if (CaseInitial(i,j))
        Set(0,i,j);
      else
        Clear(0,i,j);
}

int compte_voisin(int t,int I,int J)
{
  int i,j,n=0;
  for (j=-1;j<2;j++)
    for (i=-1;i<2;i++)
    {
      if (i==0&&j==0)
        break;
      n+=Read(t,I+i,J+j);
    }
  return n;
}

int tore_t(int T)
{
  static int t=0;
  int i,j,nb;
  if (T<t)
  {
    t=0;
    t_0();
  }
  for (;t<T;t++)
    for (j=0;j<K;j++)
      for(i=0;i<K;i++)
      {
        nb=compte_voisin(t,i,j);
        if ((Read(t,i,j)&&nb==2)||nb==3)
          Set(t+1,i,j);
        else
          Clear(t+1,i,j);
  }
  nb=0;
  for (j=0;j<K;j++)
    for(i=0;i<K;i++)
      nb+=Read(T,i,j);
  return nb;
}

void Question4()
{
  int tt[5]={0,1,10,100,1000};
  int i,nb;
  printf("4) Nombre de cellules vivantes pour divers t :\n");
  t_0();
  for (i=0;i<5;i++)
  {
    nb=tore_t(tt[i]);
    printf("A t=%i, il y a %i cellules vivantes.\n",tt[i],nb);
  }
}

/**************
*  QUESTION 6 *
***************/

/**************
*  Question 7 *
**************/
void tore_copie(int t)
{
  int i,t1=t%2,t2=1-t1;
  for (i=0;i<K*K/S+1;i++)
    tore[t2][i]=tore[t1][i];
}

//on détruit le tore[t%2], mais on l'aura sauvegardé auparavant avec copie.
int ilot(int t,int I,int J)
{
  int i,j,n=0;
  if (I==-1)
    I=K-1;
  if (J==-1)
    J=K-1;
  if (I==K)
    I=0;
  if (J==K)
    J=0;
  if (Read(t,I,J))
  {
    Clear(t,I,J);
    n=1;
    for (j=-1;j<2;j++)
      for (i=-1;i<2;i++) /* On peut rappeler la cellule elle même car elle est maintenant vide */
        n+=ilot(t,I+i,J+j);
  }
  return n;
}

void Question7()
{
  t_0();
  printf("7) L'ilot de la cellule(1,0) est consitute de %i cellules.\n",ilot(0,1,0));
}

/**************
*  Question 7 *
**************/
int nb_ilot(int t)
{
  int i,j,nb=0;
  for (j=0;j<K;j++)
    for (i=0;i<K;i++)
      if (ilot(t,i,j))
        nb++;
  return nb;
}

#define t0 48 /* Je n'ais pas écrit le code pour calculer t0 */
void Question8()
{
  int tt[4]={0,1,10,t0};
  int i,nb,t;
  printf("8) Nombre d'ilot pour divers t :\n");
  t_0();
  for (i=0;i<4;i++)
  {
    tore_t(tt[i]);
    tore_copie(tt[i]);
    t=1-(tt[i]%2);
    nb=nb_ilot(t);
    printf("A t=%i, il y a %i ilots.\n",tt[i],nb);
  }
}



int main()
{
  printf("u(0)=%i et k=%i\n",U0,K);
  Question1();
  Question2();
  Question3();
  Question4();
  Question7();
  Question8();
  getch();
}


