Zoj 1009 Enigma

从上面明文到密文的转换可以得出这样的规律    密文->明文  :

ABCDEF
+1-1+3-10-2
    即密文A ->B,C->F,E->E,

每次rotor旋转一格 则等价于 

ABCDEF
-2+1-1+3-10

此时C->B    同理rotor再旋转一次 有

ABCDEF
0-2+1-1+3-1

 此时E->B  都转换成小写就是bbb


当有三个rotor时,第一个转完一圈第二个转一个,第二个转完一圈第三个转一个

因此对测试数据

6
BADFEC
ABCDEF
ABCDEF
1
ACE

ABCDEF
+1-1+3-10-2
000000
000000

解的时候反过来从最后一个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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值