从上面明文到密文的转换可以得出这样的规律 密文->明文 :
A | B | C | D | E | F |
+1 | -1 | +3 | -1 | 0 | -2 |
每次rotor旋转一格 则等价于
A | B | C | D | E | F |
-2 | +1 | -1 | +3 | -1 | 0 |
此时C->B 同理rotor再旋转一次 有
A | B | C | D | E | F |
0 | -2 | +1 | -1 | +3 | -1 |
此时E->B 都转换成小写就是bbb
当有三个rotor时,第一个转完一圈第二个转一个,第二个转完一圈第三个转一个
因此对测试数据
6
BADFEC
ABCDEF
ABCDEF
1
ACE
有
A | B | C | D | E | F |
+1 | -1 | +3 | -1 | 0 | -2 |
0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 |
解的时候反过来从最后一个rotor开始 :A+0->A+0->A+1=B,rotor1旋转 ,C+0->C+0->C-1=B,rotor1旋转,E+0->E+0->E+3=B
有多组 Enigma 输出时除第一组数据不能有空行,其他组之间有空行
下面代码的核心部分也就是4-17行
//transform 用于得到密文到明文的转换关系 按照字典顺序从小到大
//riddle 使用rotor对应的解密表
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void transform(char r[],int ro[],int m)
{
int i;
for(i = 0;i<m;i++)
{
ro[r[i]-'A'] = ('A'+i)-r[i];
}
}
char riddle (char code,int rotor[],int m,int index)
{
int i = code-'A'-index <0? (m+(code-'A'-index)):code-'A'-index;//例如密文B的转换关系在 rotor[1-index]
int x = rotor[i]+code-'A'<0?(m+(rotor[i]+code-'A')):rotor[i]+code-'A';
return x%m+'A';
}
int main(int argc, char *argv[])
{
int index_1,index_2,index_3,m,n,i,cases;
int rotor_1[26],rotor_2[26],rotor_3[26];
char rotor[26],code;
cases = 0;
while(scanf("%d",&m)&&m!=0)
{
memset(rotor,'\0',sizeof(rotor));
scanf("%s",rotor);
transform(rotor,rotor_1,m);
scanf("%s",rotor);
transform(rotor,rotor_2,m);
scanf("%s",rotor);
transform(rotor,rotor_3,m);
scanf("%d",&n);
getchar();
if(cases++) printf("\n");
printf("Enigma %d:\n",cases);
for(i = 0;i<n;i++)
{
index_1 = index_2 = index_3 = 0;
while(scanf("%c",&code)&&code!='\n')
{
printf("%c",tolower(riddle(riddle(riddle(code,rotor_3,m,index_3),rotor_2,m,index_2),rotor_1,m,index_1)));
index_1++;//偏移量,相对于移动数组
if(index_1==m){index_1 = 0;index_2++;}
if(index_2==m){index_2 = 0;index_3++;}
if(index_3==m) index_3 = 0;
}
printf("\n");
}
}
return 0;
}