このディレクトリの索引
http://toro.2ch.net/test/read.cgi/tech/1342966104/466
#    
#  [1] 授業単元:C言語  
#  [2] 問題文:プレイフェア暗号の作成 
#        参考:http://ime.nu/www.tamagaki.com/math/PlayfairCipher.html 
#  #  
#   プレイフェア暗号(Playfair cipher)
#  
#  プレイフェア暗号はイギリス人サー・チャールズ・ホイートストン(Sir Charles Wheatstone)により開発されライアン・プレイフェア(Lyon Playfair)が普及させました。プレイフェア暗号を用いて暗号化するとき、まずキーワードまたはキーフレーズをあらかじめ決めておきます。仮にキーワードをPlayfairとします。次にこのキーワードをアルファベットが重複することなく下の5×5の表に入れていきます。
#  
#  ここで残りのセルに余ったアルファベットを挿入していくわけですが、アルファベットは26文字あって5×5では一字余ります。そこで I と J は同じセルに入れるとあらかじめ決めておきます。そこで新たに作られた表が下のようになります。
#  
#  準備ができたところで、次のメッセージを暗号化してみましょう。
#  
#  メッセージ Abandon hope, all ye who enter here.
#  
#  このメッセージをまず二文字ずつ区切っていきます。
#  
#  Ab-an-do-nh-op-ea-ll-ye-wh-oe-nt-er-he-re
#  
#  ここで7番目に ll と同じ文字が重複しているので間に x を入れます。
#  
#  Ab-an-do-nh-op-ea-lx-ly-ew-ho-en-te-rh-er-e
#  
#  そうすると最後に e が一つ余ります。ここにもやはり x を入れておきます。
#  
#  Ab-an-do-nh-op-ea-lx-ly-ew-ho-en-te-rh-er-ex
#  
#  まず最初の二文字 ab を暗号化してみましょう。ab は先ほど作った表では同じ列にあります。このときは ab の列のすぐ下の文字で置き換えます。
#  
#  つまり ab は BH に変わります。ただし一番下の文字例えば w は一番上の文字 A に変換されます。
#  
#  同様に同じ行に入る二文字も出てきたとします。例えば ap などは右隣の文字に置き換えます。
#  
#  つまり ap は YL になるわけですね。この場合も一番右の文字例えば f は一番左の文字 p に変換されます。
#  
#  最後に行も列も違う二文字が出てきた場合は次のようにします。例えば an を考えます。下の表のように a n それぞれの行および列を塗り分け、その交点となる文字を見ます。この場合、P と Q になります。
#  
#  そこで a は、a h と同じ行の P に、n は、n と同じ行の Q に変換します。つまり、
#  
#  do → RT
#  
#  nh → QE
#  
#  op → NL
#  
#  となるわけです。このルールに従って、先ほどのメッセージを暗号化すると、
#  
#  平文  Ab-an-do-nh-op-ea-lx-ly-ew-ho-en-te-rh-er-ex
#  
#  暗号文 BH PQ RT QE NL HP YV AF HU GQ NU NM BG GI KU
#  
#  これでプレイフェア暗号による暗号化が終了したわけです。
#  
#  この暗号はイギリスがボーア戦争(ブール戦争 BoreWar)で使用したといわれています。

プレイフェア暗号表の作成(_鍵文,_暗号表) :-
        鍵文を25要素のならびに拡張して(_鍵文,_25要素ならび,_鍵文字以外の変数ならび),
        'Jを除いたA-Zならびを切る'(_Jを除いたA_Zならび),
        変数を埋める(_Jを除いたA_Zならび,Chars,_鍵文字以外の変数ならび),
        'N個組'(5,_25要素のならび,_暗号表).

鍵文を25要素のならびに拡張して(_鍵文,_25要素ならび,_鍵文字ならび,_鍵文字以外の変数ならび) :-
        length(_25要素ならび,25),
        atom_chars(_鍵文,_鍵文字ならび),
        append(_鍵文字ならび,_鍵文字以外の変数ならび,_25要素ならび).

'A-Zならびを切る'(_Jを除いたA_Zならび) :-
        _切る回数 is random(113) + 1,
        トランプを切るようにならびを切る(_切る回数,25,['A','B','C','D','E','F','G','H','I','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'],_Jを除いたA_Zならび).

変数を埋める(_,_,[]).
変数を埋める(L_1,Chars,[V|R]) :-
        select(V,L_1,L_R),
        \+(member(V,Chars)),
        変数を埋める(L_R,Chars,R).


プレイフェア暗号による暗号化(_平文,_暗号文) :-
        メッセージをまず二文字ずつ区切っていきます(_平文,_二文字ずつに区切られたならび),
        プレイフェア暗号化(_二文字ずつに区切られたならび,_暗号文字ならび),
        atomic_list_concat(_暗号文字ならび,_暗号文).

メッセージをまず二文字ずつ区切っていきます(_平文,_二文字ずつに区切られたならび) :-
        atom_chars(_平文,Chars),
        すべての文字を大文字に変換(Chars,_大文字の文字ならび),
        メッセージをまず二文字ずつ区切っていきます(_大文字の文字ならび,_二文字ずつに区切られたならび).

メッセージをまず二文字ずつ区切っていきます([],[]).
メッセージをまず二文字ずつ区切っていきます(['J'|R1],[['J','J']|R2]) :-
        メッセージをまず二文字ずつ区切っていきます(R1,R2).
メッセージをまず二文字ずつ区切っていきます([A],[[A,'X']]).
メッセージをまず二文字ずつ区切っていきます([A,A|R1],[[A,'X']|R2]) :-
        メッセージをまず二文字ずつ区切っていきます([A|R1],R2).
メッセージをまず二文字ずつ区切っていきます([A,B|R1],[[A,B]|R2]) :-
        \+(A=B),
        メッセージをまず二文字ずつ区切っていきます(R1,R2).

プレイフェア暗号化(_二文字ずつに区切られたならび,_暗号文字ならび) :-
        暗号表(_暗号表),
        転置(_暗号表,_転置された暗号表),
        プレイフェア暗号化(_二文字ずつに区切られたならび,_暗号表,_転置された暗号表,_暗号文字ならび).

プレイフェア暗号化([],_,_,[]).
プレイフェア暗号化([['J','J']|R1],_暗号表,_転置された暗号表,['J'|R2]) :-
        プレイフェア暗号化(R1,_暗号表,_転置された暗号表,R2).
プレイフェア暗号化([[A,B]|R1],_暗号表,_転置された暗号表,[C,D|R2]) :-
        暗号に変換(A,B,_暗号表,C,D),
        プレイフェア暗号化(R1,_暗号表,_転置された暗号表,R2).

暗号に変換(A,B,_暗号表,_転置された暗号表,C,D) :-
        member(L,_転置された暗号表),
        'A,Bが暗号表の同一行または列にある'(A,B,L,C,D).
暗号に変換(A,B,_暗号表,_転置された暗号表,C,D) :-
        member(L,_暗号表),
        'A,Bが暗号表の同一行にある'(A,B,L,C,D).
暗号に変換(A,B,_暗号表,_転置された暗号表,C,D) :-
        暗号コードは矩形を仮想した時の他の二角(A,B,_暗号表,C,D).

'A,Bが暗号表の同一行または列にある'(A,B,L,C,D) :-
        member(A,L),
        member(B,L),
        'A,Bの次の要素'(L,A,C),
        'A,Bの次の要素'(L,B,D).

'A,Bの次の要素'(L,X,Y) :-
        append([Y|_],[X],L).
'A,Bの次の要素'(L,X,Y) :-
        append(_,[X,Y|_],L).

暗号コードは矩形を仮想した時の他の二角(A,B,_表,C,D) :-
        'A,Bの行と列位置を得る'(A,B,_表,L_1,_列_A,L_2,_列_B),
        nth1(_列_B,L_1,C),
        nth1(_列_A,L_2,D).

'A,Bの行と列位置を得る'(A,B,_表,L_1,_列_A,L_2,_列_B) :-
        nth1(_行_A,_表,L_1),
        nth1(_列_A,L_1,A),
        nth1(_行_B,_表,L_2),
        nth1(_列_B,L_2,B).