0

復号化機能を機能させる方法を見つけようとして、多くの問題を抱えています。メッセージが3で割り切れる理想的なケースでは機能しますが、その後は完全に失われます。これを2つのレールで動作させることができたので、何をしなければならないかについて漠然とした考えがありますが、3つのレールではより多くの可能性があります. 私はかなり迷っています:(また、これらのprintステートメントはすべて、プログラム内で何が起こっているのかを理解しようとするためのものです。

import sys

def main():
    plaintext="abcdefgh"
    print(threeRailEncrypt(plaintext))
    print(threeRailDecrypt(threeRailEncrypt(plaintext)))


def threeRailEncrypt(plaintext):
    ciphertext=""
    rail1=""
    rail2=""
    rail3=""

    for i in range(len(plaintext)):
        if i%3 == 0:
            rail1=rail1+plaintext[i]
        elif i%3 == 1:
            rail2=rail2+plaintext[i]
        else:
            rail3=rail3+plaintext[i]

    ciphertext=rail1+rail2+rail3

    return(ciphertext)

def threeRailDecrypt(msg):
    if len(msg)%3==0:
        third=len(msg)//3
        print(third)
        rail1=msg[:third]
        rail2=msg[third:third*2]
        rail3=msg[third*2:]
        print(rail1,rail2,rail3)
        dm=""
        for i in range(third):
            dm=dm+rail1[i]
            dm=dm+rail2[i]
            dm=dm+rail3[i]
    else:
        third=(len(msg)//3)+1
        print(third)
        rail1=msg[:third]
        rail2=msg[third:third*2]
        rail3=msg[third*2:]
        print(rail1,rail2,rail3)
        dm=""
        for i in range(third):
            dm=dm+rail1[i]
            print(dm)
            dm=dm+rail2[i]
            print(dm)
            dm=dm+rail3[i]
            print(dm)
            if  len(rail2)>len(rail3):
                dm=dm+rail2[-1]
        return(dm)
main()

進捗-

def threeRailDecrypt(cypher, rails = 3):
    length = len (cypher)
    for i in range(rails):
        lens=(length//rails)
        if length % rails > i:
            lens=lens+1
        print(lens)
4

3 に答える 3

1

まったく異なるアプローチとより明示的なコードを使用して、2 番目の回答を追加します。

def dec2 (cypher):
    length = len (cypher)
    if length < 4: return cypher
    third = length // 3 + (1 if length % 3 else 0)
    cypher = list (cypher)
    if length % 3 == 1: cypher.insert (third * 2 - 1, '')
    return ''.join (''.join (cypher [i::third] ) for i in range (third) )

または、先生にショックを与えるだけです。

enc = lambda p:''.join(p[_::3]for _ in range(3))
dec = lambda c:c if len(c)<4 else(lambda *a:(lambda c,t:
''.join(''.join(c[i::t])for i in range(t)))((lambda c,t,
l:c[:t*2-1]+(['']if l%3==1 else[])+c[t*2-1:])(*a),a [2])
)(*(lambda c:(list(c),len(c),len(c)//3+(1 if len(c)%3
else 0)))(c))
于 2013-10-03T01:33:16.283 に答える
0

これはうまくいくはずです。異なるレールの長さを把握する必要があります。

from itertools import zip_longest as zip

def enc (plain, rails = 3):
    return ''.join (plain [i::rails] for i in range (rails) )

def dec (cypher, rails = 3):
    length = len (cypher)
    lens = [length // rails + (1 if length % rails > i else 0) for i in range (rails) ]
    paths = [cypher [sum (lens [:i] ):sum (lens [:i + 1] ) ] for i in range (rails) ]
    return ''.join (''.join (x for x in x if x) for x in zip (*paths) )

plain = 'abcdefghijk'
for i in range (10):
    a = plain [:i]
    b = enc (a)
    c = dec (b)
    print (a, b, c)

使用されるレールの任意の数 (>0) で機能するはずです。


編集: zip_longest なし:

def enc (plain, rails = 3):
    return ''.join (plain [i::rails] for i in range (rails) )

def dec (cypher, rails = 3):
    length = len (cypher)
    lens = [length // rails + (1 if length % rails > i else 0) for i in range (rails) ]
    paths = [cypher [sum (lens [:i]):sum (lens [:i + 1] ) ] for i in range (rails) ]
    maxLen = len (paths [0] )
    paths = [list (path) + ( [] if len (path) == maxLen else [''] ) for path in paths]
    return ''.join (''.join (x) for x in zip (*paths) )

復号化の説明:

length = len (cypher)

便宜上、暗号テキストの長さをローカル変数に格納します。

lens = [length // rails + (1 if length % rails > i else 0) for i in range (rails) ]

次に、各レールの長さを計算します。各レールの長さは、暗号テキストの長さをレールの数 (あなたの場合は 3) で割ったものであり、長さが正確に割り切れない場合は(if部分) を加えたものかもしれません。1

paths = [cypher [sum (lens [:i] ):sum (lens [:i + 1] ) ] for i in range (rails) ]

次に、計算したばかりのレールの長さに応じて、サイファー テキストをさまざまなレールにスライスします。

maxLen = len (paths [0] )

レールの最大長は、最初のレールの長さと同じです。

paths = [list (path) + ( [] if len (path) == maxLen else [''] ) for path in paths]

ここで、短すぎる各レールの端に空の文字を追加して、すべてのレールが同じ長さになり、圧縮できるようにします。

return ''.join (''.join (x) for x in zip (*paths) )

レールを圧縮し、結果の各タプルを文字列に結合してから、それらすべての文字列を 1 つの長い文字列に結合して返します。

于 2013-10-03T00:26:50.203 に答える