// Bombe-like crib attack on Enigma I (reflector B). Rings: L=0,M=0 fixed (absorbed), R ring enumerated.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static const char *W[5]={"EKMFLGDQVZNTOWYHXUSPAIBRCJ","AJDKSIRUXBLHWTMCQGZNPYFVOE","BDFHJLCPRTXVZNYEIWGAKMUSQO","ESOVPZJAYQUIRHXLNFTGKDCMWB","VZBRGITYUPSDNHLXAWMJQOFECK"};
static const char NOTCH[5]={'Q'-'A','E'-'A','V'-'A','J'-'A','Z'-'A'};
static const char *REF="YRUHQSLDPXNGOKMIEBFZCWVJAT";
static const char *CT="GZEQOBWMJZOJTIBZPVHNSHJWSCLRQLYFIZKBQNPBPYOCHMIJSCRVURXSEHDYBNRZLZBODHRZNQNOARXYOIVVWKFOCOAZEBVLOLEBTEJBXFROC";
static const char *CRIB="WETTERVORHERSAGEBISKAYA";
int F[5][26],B[5][26],R[26];
static unsigned char T[26][26][26][26];
static int rot(int w,int x,int off,int fwd){int y=(x+off)%26; y= fwd?F[w][y]:B[w][y]; return (y-off+26)%26;}
int L; int pa[64],pb[64];
int adj[26][64],adjn[26],adjpos[26][64];
int test(unsigned char **E,int t,int h,int *S){
  for(int i=0;i<26;i++)S[i]=-1;
  int q[64],qn=0; S[t]=h;S[h]=t;q[qn++]=t;if(h!=t)q[qn++]=h;
  for(int qi=0;qi<qn;qi++){int x=q[qi];int sx=S[x];
    for(int k=0;k<adjn[x];k++){int y=adj[x][k];int i=adjpos[x][k];int v=E[i][sx];
      if(S[y]==-1){ if(S[v]!=-1) return 0; S[y]=v;S[v]=y;q[qn++]=y;if(v!=y)q[qn++]=v;}
      else if(S[y]!=v) return 0;}}
  int pairs=0;for(int i=0;i<26;i++)if(S[i]>i)pairs++; if(pairs>10)return 0;
  return 1;
}
int main(int argc,char**argv){
  int o0=atoi(argv[1]),o1=atoi(argv[2]);
  for(int w=0;w<5;w++)for(int i=0;i<26;i++){F[w][i]=W[w][i]-'A';B[w][W[w][i]-'A']=i;}
  for(int i=0;i<26;i++)R[i]=REF[i]-'A';
  L=strlen(CRIB);
  for(int i=0;i<L;i++){int a=CRIB[i]-'A',b=CT[i]-'A';adj[a][adjn[a]]=b;adjpos[a][adjn[a]++]=i;adj[b][adjn[b]]=a;adjpos[b][adjn[b]++]=i;}
  int tl=0;for(int i=0;i<26;i++)if(adjn[i]>adjn[tl])tl=i;
  int ord=0;
  for(int a=0;a<5;a++)for(int b=0;b<5;b++)for(int c=0;c<5;c++){ if(a==b||b==c||a==c)continue; int my=ord++; if(my<o0||my>=o1)continue;
    // a=left,b=mid,c=right
    for(int l=0;l<26;l++)for(int m=0;m<26;m++)for(int r=0;r<26;r++)for(int x=0;x<26;x++){
      int y=rot(c,x,r,1);y=rot(b,y,m,1);y=rot(a,y,l,1);y=R[y];y=rot(a,y,l,0);y=rot(b,y,m,0);y=rot(c,y,r,0);T[l][m][r][x]=y;}
    long stops=0;
    for(int rR=0;rR<26;rR++)for(int pL=0;pL<26;pL++)for(int pM=0;pM<26;pM++)for(int pR=0;pR<26;pR++){
      unsigned char *E[64]; int l=pL,m=pM,r=pR;
      for(int i=0;i<L;i++){ int mstep=(m==NOTCH[b]); if(r==NOTCH[c]||mstep){ if(mstep) l=(l+1)%26; m=(m+1)%26;} r=(r+1)%26;
        E[i]=T[l][m][(r-rR+26)%26];}
      int S[26];
      for(int h=0;h<26;h++) if(test(E,tl,h,S)){ stops++;
        printf("%c%c%c rR=%d pos=%c%c%c plugs=",'1'+a,'1'+b,'1'+c,rR,'A'+pL,'A'+pM,'A'+pR);
        for(int i=0;i<26;i++)printf("%c",S[i]<0?'.':'A'+S[i]); printf("\n");}
    }
    fprintf(stderr,"order %c%c%c stops %ld\n",'1'+a,'1'+b,'1'+c,stops);
  }
}
