#include"lib.h"

int mot[MAX], m_i[MAX], m_o[MAX], P[100][100];
int i, a_i = 2, a_o = 6, j, k, size, mmx = 0, n2;
int64_t cc;
FILE *out ;
char prog[100];

void aff(int max){
  printf("%d cc=%lld %s", max, cc, prog); date("");
}//*/

/*void aff(int max){
  out = fopen(prog, "wt");
  fprintf(out, "%d cc=%lld\n", max, cc);
  printf("%d cc=%lld %s", max, cc, prog); date("");
  for(k = 0; k < max; k++) fprintf(out, "%d%s", mot[k], k % 100 == 99 ? "\n" : "");
  fclose(out);
}//*/

void permut(int *l, int *r, int *p){
  *r = n2;
  for(k = 0; k < a_o-2; k++) *r -= l[k];
  for(k = 1; k < a_o-2; k++) r[k] = l[p[k]];
}//*/

/*
  if(xx){ //4102(3) //6
  }else{ //4021(3)
  if(xx){ //51032(4) //7
  }else{ //50213(4)
  if(xx){ //610243(5) //8
  }else{ //602143(5)
//*/

int check(int *m, int i){
  permut(m_o+(a_o-1)*i+1, m_o+(a_o-1)*(i+1)+1, P[m[i]]);
  m_o[(a_o-1)*(i+2)] = 0;
  for(k = (a_o-1)*(i+1)+1; k <= (a_o-1)*(i+2); k++) if(!rep(m_o, k, a_o, a_o-1, 1, 1) /*|| !rep(m_o, k, 143, 120, 1, 6)*/) return 0;
  return 1;
  // 143/120=1.191666666
}

int ok0(){
  i++;
  for(j = 1; j < a_o-1; j++) if(m_o[(a_o-1)*i+j] != m_o[j]){ i -= 2; return 0; }
  mot[i] = 0;
  if(!check(mot, i)){ i -= 2; return 0; }
  for(j = 0; j < size; j++){
    mot[size+j] = mot[j];
    if(!check(mot, size+j)){ i -= 2; return 0; }
  }
  mot[++i] = 1;
  if(!check(mot, i)){ i -= 3; return 0; }
  return 1;
}//*/

int ok1(){
  i++;
  for(j = 1; j < a_o-1; j++) if(m_o[(a_o-1)*i+j] != m_o[(a_o-1)*size+j]){ i -= 2; return 0; }
  mot[i] = 1;
  if(!check(mot, i)){ i -= 2; return 0; }
  for(j = 0; j < 1000000; j++){
    m_i[j] = mot[m_i[j/size]*size+j%size];
    if(j > mmx) if(!((mmx = j)%1000)){
      printf("mmx=%d", mmx); date("");
      for(k = 0; k < a_i*size; ){ printf("%d", mot[k]); if(!((++k)%size)) printf("\n"); }
    }
    if(!check(m_i, j)){ i -= 2; return 0; }
  }
  return 1;
}//*/

int A(){
  printf("%s", prog); date("");
  for(*mot = i = 0; ;) if(!check(mot, i)){
    while(mot[i] == a_i-1) if(--i < 0) return 0;
    mot[i]++;
  }else{
    if((mmx < i) && (!((++mmx)%10000))) aff(mmx);
    mot[++i] = 0;
    if(!((++cc)%1000)) aff(mmx);
    //if(!((++cc)%10000000)) aff(mmx);
  }
  return 1;
}//*/

int B(){
  printf("a_o=%d size=%d", a_o, size); date("");
  for(*mot = i = 0; ;) if(!check(mot, i)){
    here: while(mot[i] == a_i-1 || i == size-1) if(--i < 1) return 1;
    mot[i]++;
  }else if(i == size-2) if(!ok0()) goto here; else continue;
  else if(i == 2*size-2) if(!ok1()) goto here; else break;
  else mot[++i] = 0;
  for(k = 0; k < a_i*size; ){ printf("%d", mot[k]); if(!((++k)%size)) printf("\n"); }
  printf("OK size=%d", size); date("");
  return 0;
}//*/

void usage(){
  printf("Usage: dg+ size a_o P[0] P[1]..\n");
  printf("Result in the paper: dg+ 25 6 52134 51324\n");
  exit(0);
}

int main(int ac, char **av){
  if(ac < 5) usage();
  a_i = ac-3;
  size = atoi(av[1]);
  a_o = atoi(av[2]);
  n2 = a_o*(a_o-1)/2;
  for(i = 0; i < a_i; i++) for(j = 0; j < a_o; j++) P[i][j] = av[i+3][j]-'1';
  sprintf(prog, "%s_%d_%d.txt", basename(*av), a_i, a_o);
  printf("P[0]=%s P[1]=%s %s\n", av[3], av[4], prog);
  for(i = 0; i < a_o; i++) m_o[i] = i;
  m_o[a_o-1] = *m_i = 0;
  //if(A()) printf("OK"); else printf("FAILED mmx=%d cc=%lld", mmx, cc); date("");
  for(; B() && size < 700; size++) printf("mmx=%d\n", mmx);
}
/*
a_o = 6 mmx=107000: 13/02/2006 18/54/14
001000101011101
100110101100101
*/