文字をずらすことによって作られる暗号をシーザー暗号といいます。今回はアルファベット小文字a...zをずらすことによって出来た暗号を復号化します(右に1文字ずらすとzはぐるっと回ってaになります)。
入力されるのは暗号化された文字列です。ヒントは復号化した文字列にthe,this,thatのいずれかの単語が含まれていることです。今回は、この単語のいずれかが含まれていれば復号化した文字列を出力し終了してください。
暗号化されたデータに含まれる文字はアルファベットの小文字、ピリオド、空白、改行のみです。このうち暗号化を行っているのはアルファベット小文字のみです。また、文字数は80文字以下です。
詳しくは原文参照。
暗号化された文字列
複合化した文字列
xlmw mw xli tmgxyvi xlex m xsso mr xli xvmt.
this is the picture that i took in the trip.
文字列マッチします。その際、ちゃんと単語になっているように注意します。他の単語の一部分にマッチしないようにしましょう。
#include <stdio.h> #include <string.h> int scan(char *str,int max) { int i; for(i=0;i<max;i++){ if(!strncmp(&(str[i]),"this ",5))return 1; if(!strncmp(&(str[i]),"that ",5))return 1; if(!strncmp(&(str[i]),"the ",4))return 1; if(!strncmp(&(str[i]),"this.",5))return 1; if(!strncmp(&(str[i]),"that.",5))return 1; if(!strncmp(&(str[i]),"the.",4))return 1; //次の単語の始まりをさがす for(i++;;i++){ if(str[i] == ' ' || str[i] == '.'){ break; } } } return 0; } int main(){ char in[82]; int n,i; gets(in); n = strlen(in); while(1){ for(i=0;i<n;i++){ if(in[i] !=' ' && in[i] != '.'){ in[i] = in[i] + 1; if(in[i] == 'z'+1)in[i] ='a'; } } if(scan(in,n))break; } printf("%s\n",in); return 0; }
今回のマッチ作業は非常に効率が悪いです。ですが、まあ、こんなモンでしょう。最初は単純に1文字ずつずらしながらマッチしていましたが、それだと他の単語の途中にマッチする可能性があったので改良しました。実際にはもう3通り最後が改行になっている文字列ともマッチした方が良かったのですが、それは省略です。きっとピリオドで終わってくれるでしょう。