#include <stdio.h>
#include <string.h>
#include <math.h>

const char GENERATOR[]="golf/romanc.pl v0.02";
int check_start = 0;
unsigned char assign[256];
unsigned char val[10][16] = { "a", "b", "cd", "efg", "hi", "j", "kl", "mno", "pqrs", "tu" };
unsigned int val_len[10];
unsigned int model_len[10];
char *model[10] = { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
unsigned char I_set[256];
unsigned char V_set[256];
unsigned char X_set[256];
int assigner(void);

int main(void) {
    int i,m;

    memset(assign, 0, sizeof(assign));
    memset(I_set, 0, sizeof(I_set));
    memset(V_set, 0, sizeof(V_set));
    memset(X_set, 0, sizeof(X_set));
    for (i=0; i<10; i++) model_len[i] = strlen(model[i]);

    /* Sanity check */
    assigner();
    printf("0=0\n");
    fflush(stdout);

    /* Set up a val try loop here */
    for (m=1; m<10; m++) {
        double n;
        for (n=1; n<10000; n++) {
            int x;
            for (x=0; x<128; x++) {
                double accu;
                for (i=0, accu=0; i<10; i++, accu = accu*10+m) {
                    double r = fmod(accu, n);
                    sprintf(val[i], "%d", ((int) r) ^ x);
                }
                if (assigner()) {
                    printf("m=%d,n=%d,x=%d\n", m, (int) n,  x);
                    fflush(stdout);
                }
            }
        }
    }

    return 0;
}

int assigner(void) {
    int i, found=0;
    unsigned int i80, i81, i82, i83, i30, i31, i32, i70, i71, i72, i20, i21, i40, i41, i60, i61, i90, i91, i10, i50;

    for (i=0; i<10; i++) {
        val_len[i] = strlen(val[i]);
        if (val_len[i] < model_len[i]) return 0;
    }

    for (i80=0; i80 < val_len[8]-3; i80++) {
      unsigned int c80 = val[8][i80];
      /* printf("    Try %c for V (i80=%d)\n", c80, i80); */
      if (assign[c80] && assign[c80] != model[8][0]) continue;
      V_set[c80]++;
      assign[c80] = model[8][0];
      for (i=check_start; i<10; i++) {
          const char *m = model[i];
          const char *v;
          for (v = val[i]; *v; v++) {
              unsigned char av = assign[*v];
              if (av == 0) continue;
              while (*m != av) {
                  if (*m == 0) goto L80;
                  m++;
              }
              m++;
          }
      }
      for (i81=i80+1; i81 < val_len[8]-2; i81++) {
        unsigned int c81 = val[8][i81];
        /* printf("      Try %c for I (i81=%d)\n", c81, i81); */
        if (assign[c81] && assign[c81] != model[8][1]) continue;
        I_set[c81]++;
        assign[c81] = model[8][1];
        for (i=check_start; i<10; i++) {
            const char *m = model[i];
            const char *v;
            for (v = val[i]; *v; v++) {
                unsigned char av = assign[*v];
                if (av == 0) continue;
                while (*m != av) {
                    if (*m == 0) goto L81;
                    m++;
                }
                m++;
            }
        }
        for (i82=i81+1; i82 < val_len[8]-1; i82++) {
          unsigned int c82 = val[8][i82];
          /* printf("        Try %c for I (i82=%d)\n", c82, i82); */
          if (assign[c82] && assign[c82] != model[8][2]) continue;
          I_set[c82]++;
          assign[c82] = model[8][2];
          for (i=check_start; i<10; i++) {
              const char *m = model[i];
              const char *v;
              for (v = val[i]; *v; v++) {
                  unsigned char av = assign[*v];
                  if (av == 0) continue;
                  while (*m != av) {
                      if (*m == 0) goto L82;
                      m++;
                  }
                  m++;
              }
          }
          for (i83=i82+1; i83 < val_len[8]; i83++) {
            unsigned int c83 = val[8][i83];
            /* printf("          Try %c for I (i83=%d)\n", c83, i83); */
            if (assign[c83] && assign[c83] != model[8][3]) continue;
            I_set[c83]++;
            assign[c83] = model[8][3];
            for (i=check_start; i<10; i++) {
                const char *m = model[i];
                const char *v;
                for (v = val[i]; *v; v++) {
                    unsigned char av = assign[*v];
                    if (av == 0) continue;
                    while (*m != av) {
                        if (*m == 0) goto L83;
                        m++;
                    }
                    m++;
                }
            }
            for (i30=0; i30 < val_len[3]-2; i30++) {
              unsigned int c30 = val[3][i30];
              /* printf("            Try %c for I (i30=%d)\n", c30, i30); */
              if (assign[c30] && assign[c30] != model[3][0]) continue;
              I_set[c30]++;
              assign[c30] = model[3][0];
              for (i=check_start; i<10; i++) {
                  const char *m = model[i];
                  const char *v;
                  for (v = val[i]; *v; v++) {
                      unsigned char av = assign[*v];
                      if (av == 0) continue;
                      while (*m != av) {
                          if (*m == 0) goto L30;
                          m++;
                      }
                      m++;
                  }
              }
              for (i31=i30+1; i31 < val_len[3]-1; i31++) {
                unsigned int c31 = val[3][i31];
                /* printf("              Try %c for I (i31=%d)\n", c31, i31); */
                if (assign[c31] && assign[c31] != model[3][1]) continue;
                I_set[c31]++;
                assign[c31] = model[3][1];
                for (i=check_start; i<10; i++) {
                    const char *m = model[i];
                    const char *v;
                    for (v = val[i]; *v; v++) {
                        unsigned char av = assign[*v];
                        if (av == 0) continue;
                        while (*m != av) {
                            if (*m == 0) goto L31;
                            m++;
                        }
                        m++;
                    }
                }
                for (i32=i31+1; i32 < val_len[3]; i32++) {
                  unsigned int c32 = val[3][i32];
                  /* printf("                Try %c for I (i32=%d)\n", c32, i32); */
                  if (assign[c32] && assign[c32] != model[3][2]) continue;
                  I_set[c32]++;
                  assign[c32] = model[3][2];
                  for (i=check_start; i<10; i++) {
                      const char *m = model[i];
                      const char *v;
                      for (v = val[i]; *v; v++) {
                          unsigned char av = assign[*v];
                          if (av == 0) continue;
                          while (*m != av) {
                              if (*m == 0) goto L32;
                              m++;
                          }
                          m++;
                      }
                  }
                  for (i70=0; i70 < val_len[7]-2; i70++) {
                    unsigned int c70 = val[7][i70];
                    /* printf("                  Try %c for V (i70=%d)\n", c70, i70); */
                    if (assign[c70] && assign[c70] != model[7][0]) continue;
                    V_set[c70]++;
                    assign[c70] = model[7][0];
                    for (i=check_start; i<10; i++) {
                        const char *m = model[i];
                        const char *v;
                        for (v = val[i]; *v; v++) {
                            unsigned char av = assign[*v];
                            if (av == 0) continue;
                            while (*m != av) {
                                if (*m == 0) goto L70;
                                m++;
                            }
                            m++;
                        }
                    }
                    for (i71=i70+1; i71 < val_len[7]-1; i71++) {
                      unsigned int c71 = val[7][i71];
                      /* printf("                    Try %c for I (i71=%d)\n", c71, i71); */
                      if (assign[c71] && assign[c71] != model[7][1]) continue;
                      I_set[c71]++;
                      assign[c71] = model[7][1];
                      for (i=check_start; i<10; i++) {
                          const char *m = model[i];
                          const char *v;
                          for (v = val[i]; *v; v++) {
                              unsigned char av = assign[*v];
                              if (av == 0) continue;
                              while (*m != av) {
                                  if (*m == 0) goto L71;
                                  m++;
                              }
                              m++;
                          }
                      }
                      for (i72=i71+1; i72 < val_len[7]; i72++) {
                        unsigned int c72 = val[7][i72];
                        /* printf("                      Try %c for I (i72=%d)\n", c72, i72); */
                        if (assign[c72] && assign[c72] != model[7][2]) continue;
                        I_set[c72]++;
                        assign[c72] = model[7][2];
                        for (i=check_start; i<10; i++) {
                            const char *m = model[i];
                            const char *v;
                            for (v = val[i]; *v; v++) {
                                unsigned char av = assign[*v];
                                if (av == 0) continue;
                                while (*m != av) {
                                    if (*m == 0) goto L72;
                                    m++;
                                }
                                m++;
                            }
                        }
                        for (i20=0; i20 < val_len[2]-1; i20++) {
                          unsigned int c20 = val[2][i20];
                          /* printf("                        Try %c for I (i20=%d)\n", c20, i20); */
                          if (assign[c20] && assign[c20] != model[2][0]) continue;
                          I_set[c20]++;
                          assign[c20] = model[2][0];
                          for (i=check_start; i<10; i++) {
                              const char *m = model[i];
                              const char *v;
                              for (v = val[i]; *v; v++) {
                                  unsigned char av = assign[*v];
                                  if (av == 0) continue;
                                  while (*m != av) {
                                      if (*m == 0) goto L20;
                                      m++;
                                  }
                                  m++;
                              }
                          }
                          for (i21=i20+1; i21 < val_len[2]; i21++) {
                            unsigned int c21 = val[2][i21];
                            /* printf("                          Try %c for I (i21=%d)\n", c21, i21); */
                            if (assign[c21] && assign[c21] != model[2][1]) continue;
                            I_set[c21]++;
                            assign[c21] = model[2][1];
                            for (i=check_start; i<10; i++) {
                                const char *m = model[i];
                                const char *v;
                                for (v = val[i]; *v; v++) {
                                    unsigned char av = assign[*v];
                                    if (av == 0) continue;
                                    while (*m != av) {
                                        if (*m == 0) goto L21;
                                        m++;
                                    }
                                    m++;
                                }
                            }
                            for (i40=0; i40 < val_len[4]-1; i40++) {
                              unsigned int c40 = val[4][i40];
                              /* printf("                            Try %c for I (i40=%d)\n", c40, i40); */
                              if (assign[c40] && assign[c40] != model[4][0]) continue;
                              I_set[c40]++;
                              assign[c40] = model[4][0];
                              for (i=check_start; i<10; i++) {
                                  const char *m = model[i];
                                  const char *v;
                                  for (v = val[i]; *v; v++) {
                                      unsigned char av = assign[*v];
                                      if (av == 0) continue;
                                      while (*m != av) {
                                          if (*m == 0) goto L40;
                                          m++;
                                      }
                                      m++;
                                  }
                              }
                              for (i41=i40+1; i41 < val_len[4]; i41++) {
                                unsigned int c41 = val[4][i41];
                                /* printf("                              Try %c for V (i41=%d)\n", c41, i41); */
                                if (assign[c41] && assign[c41] != model[4][1]) continue;
                                V_set[c41]++;
                                assign[c41] = model[4][1];
                                for (i=check_start; i<10; i++) {
                                    const char *m = model[i];
                                    const char *v;
                                    for (v = val[i]; *v; v++) {
                                        unsigned char av = assign[*v];
                                        if (av == 0) continue;
                                        while (*m != av) {
                                            if (*m == 0) goto L41;
                                            m++;
                                        }
                                        m++;
                                    }
                                }
                                for (i60=0; i60 < val_len[6]-1; i60++) {
                                  unsigned int c60 = val[6][i60];
                                  /* printf("                                Try %c for V (i60=%d)\n", c60, i60); */
                                  if (assign[c60] && assign[c60] != model[6][0]) continue;
                                  V_set[c60]++;
                                  assign[c60] = model[6][0];
                                  for (i=check_start; i<10; i++) {
                                      const char *m = model[i];
                                      const char *v;
                                      for (v = val[i]; *v; v++) {
                                          unsigned char av = assign[*v];
                                          if (av == 0) continue;
                                          while (*m != av) {
                                              if (*m == 0) goto L60;
                                              m++;
                                          }
                                          m++;
                                      }
                                  }
                                  for (i61=i60+1; i61 < val_len[6]; i61++) {
                                    unsigned int c61 = val[6][i61];
                                    /* printf("                                  Try %c for I (i61=%d)\n", c61, i61); */
                                    if (assign[c61] && assign[c61] != model[6][1]) continue;
                                    I_set[c61]++;
                                    assign[c61] = model[6][1];
                                    for (i=check_start; i<10; i++) {
                                        const char *m = model[i];
                                        const char *v;
                                        for (v = val[i]; *v; v++) {
                                            unsigned char av = assign[*v];
                                            if (av == 0) continue;
                                            while (*m != av) {
                                                if (*m == 0) goto L61;
                                                m++;
                                            }
                                            m++;
                                        }
                                    }
                                    for (i90=0; i90 < val_len[9]-1; i90++) {
                                      unsigned int c90 = val[9][i90];
                                      /* printf("                                    Try %c for I (i90=%d)\n", c90, i90); */
                                      if (assign[c90] && assign[c90] != model[9][0]) continue;
                                      I_set[c90]++;
                                      assign[c90] = model[9][0];
                                      for (i=check_start; i<10; i++) {
                                          const char *m = model[i];
                                          const char *v;
                                          for (v = val[i]; *v; v++) {
                                              unsigned char av = assign[*v];
                                              if (av == 0) continue;
                                              while (*m != av) {
                                                  if (*m == 0) goto L90;
                                                  m++;
                                              }
                                              m++;
                                          }
                                      }
                                      for (i91=i90+1; i91 < val_len[9]; i91++) {
                                        unsigned int c91 = val[9][i91];
                                        /* printf("                                      Try %c for X (i91=%d)\n", c91, i91); */
                                        if (assign[c91] && assign[c91] != model[9][1]) continue;
                                        X_set[c91]++;
                                        assign[c91] = model[9][1];
                                        for (i=check_start; i<10; i++) {
                                            const char *m = model[i];
                                            const char *v;
                                            for (v = val[i]; *v; v++) {
                                                unsigned char av = assign[*v];
                                                if (av == 0) continue;
                                                while (*m != av) {
                                                    if (*m == 0) goto L91;
                                                    m++;
                                                }
                                                m++;
                                            }
                                        }
                                        for (i10=0; i10 < val_len[1]; i10++) {
                                          unsigned int c10 = val[1][i10];
                                          /* printf("                                        Try %c for I (i10=%d)\n", c10, i10); */
                                          if (assign[c10] && assign[c10] != model[1][0]) continue;
                                          I_set[c10]++;
                                          assign[c10] = model[1][0];
                                          for (i=check_start; i<10; i++) {
                                              const char *m = model[i];
                                              const char *v;
                                              for (v = val[i]; *v; v++) {
                                                  unsigned char av = assign[*v];
                                                  if (av == 0) continue;
                                                  while (*m != av) {
                                                      if (*m == 0) goto L10;
                                                      m++;
                                                  }
                                                  m++;
                                              }
                                          }
                                          for (i50=0; i50 < val_len[5]; i50++) {
                                            unsigned int c50 = val[5][i50];
                                            /* printf("                                          Try %c for V (i50=%d)\n", c50, i50); */
                                            if (assign[c50] && assign[c50] != model[5][0]) continue;
                                            V_set[c50]++;
                                            assign[c50] = model[5][0];
                                            for (i=check_start; i<10; i++) {
                                                const char *m = model[i];
                                                const char *v;
                                                for (v = val[i]; *v; v++) {
                                                    unsigned char av = assign[*v];
                                                    if (av == 0) continue;
                                                    while (*m != av) {
                                                        if (*m == 0) goto L50;
                                                        m++;
                                                    }
                                                    m++;
                                                }
                                            }
                                            found=1;
                                            for (i=0; i<10;i++) {
                                                fputs(val[i], stdout);
                                                putchar(' ');
                                            }
                                            fputs("=>", stdout);
                                            for (i=0; i<10;i++) {
                                                unsigned char *v;
                                                putchar(' ');
                                                for (v=val[i]; *v; v++) putchar(assign[*v] ? assign[*v] : *v);
                                            }
                                            fputs(" I=[", stdout);
                                            for (i=0; i<256; i++) if (assign[i] == 'I') putchar(i);
                                            putchar(']');
                                            fputs(" V=[", stdout);
                                            for (i=0; i<256; i++) if (assign[i] == 'V') putchar(i);
                                            putchar(']');
                                            fputs(" X=[", stdout);
                                            for (i=0; i<256; i++) if (assign[i] == 'X') putchar(i);
                                            putchar(']');
                                            putchar('\n');
                                           L50:
                                            if (--V_set[c50]) break;
                                            else assign[c50] = 0;
                                          }
                                         L10:
                                          if (--I_set[c10]) break;
                                          else assign[c10] = 0;
                                        }
                                       L91:
                                        if (--X_set[c91]) break;
                                        else assign[c91] = 0;
                                      }
                                     L90:
                                      if (--I_set[c90]) break;
                                      else assign[c90] = 0;
                                    }
                                   L61:
                                    if (--I_set[c61]) break;
                                    else assign[c61] = 0;
                                  }
                                 L60:
                                  if (--V_set[c60]) break;
                                  else assign[c60] = 0;
                                }
                               L41:
                                if (--V_set[c41]) break;
                                else assign[c41] = 0;
                              }
                             L40:
                              if (--I_set[c40]) break;
                              else assign[c40] = 0;
                            }
                           L21:
                            if (--I_set[c21]) break;
                            else assign[c21] = 0;
                          }
                         L20:
                          if (--I_set[c20]) break;
                          else assign[c20] = 0;
                        }
                       L72:
                        if (--I_set[c72]) break;
                        else assign[c72] = 0;
                      }
                     L71:
                      if (--I_set[c71]) break;
                      else assign[c71] = 0;
                    }
                   L70:
                    if (--V_set[c70]) break;
                    else assign[c70] = 0;
                  }
                 L32:
                  if (--I_set[c32]) break;
                  else assign[c32] = 0;
                }
               L31:
                if (--I_set[c31]) break;
                else assign[c31] = 0;
              }
             L30:
              if (--I_set[c30]) break;
              else assign[c30] = 0;
            }
           L83:
            if (--I_set[c83]) break;
            else assign[c83] = 0;
          }
         L82:
          if (--I_set[c82]) break;
          else assign[c82] = 0;
        }
       L81:
        if (--I_set[c81]) break;
        else assign[c81] = 0;
      }
     L80:
      if (--V_set[c80]) break;
      else assign[c80] = 0;
    }
    return found;
}
