1

Eventually I will be able to post simple questions like this in a chat room, but for now I must post it. I am still struggling with comparison issues in Python. I have a list containing strings that I obtained from a file. I have a function which takes in the word list (previously created from a file) and some 'ciphertext'. I am trying to Brute Force crack the ciphertext using a Shift Cipher. My issue is the same as with comparing integers. Although I can see when trying to debug using print statements, that my ciphertext will be shifted to a word in the word list, it never evaluates to True. I am probably comparing two different variable types or a /n is probably throwing the comparison off. Sorry for all of the posts today, I am doing lots of practice problems today in preparation for an upcoming assignment.

  def shift_encrypt(s, m):

   shiftAmt = s % 26
   msgAsNumList = string2nlist(m)

   shiftedNumList = add_val_mod26(msgAsNumList, shiftAmt)
   print 'Here is the shifted number list: ', shiftedNumList

   # Take the shifted number list and convert it back to a string
   numListtoMsg = nlist2string(shiftedNumList)
   msgString = ''.join(numListtoMsg)

   return msgString

 def add_val_mod26(nlist, value):
   newValue = value % 26
   print 'Value to Add after mod 26: ', newValue
   listLen = len(nlist)
   index = 0
   while index < listLen:
       nlist[index] = (nlist[index] + newValue) % 26
       index = index + 1
   return nlist

 def string2nlist(m):
   characters =    ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
   numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]
   newList = []
   msgLen = len(m)         # var msgLen will be an integer of the length

   index = 0               # iterate through message length in while loop
   while index < msgLen:
       letter = m[index]   # iterate through message m
       i = 0
       while i < 26:
           if letter == characters[i]:
               newList.append(numbers[i])
           i = i + 1
       index = index + 1
    return newList

  def nlist2string(nlist):
    characters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]
    newList = []
    nListLen = len(nlist)

    index = 0
    while index < nListLen:
        num = nlist[index]
        newNum = num % 26
        i = 0
        while i < 26:
            num1 = newNum
            num2 = numbers[i]
            if (num1 == num2):
            newList.append(characters[i])
        i = i + 1
    index = index + 1
    return newList


  def wordList(filename):

    fileObject = open(filename, "r+")                    
    wordsList = fileObject.readlines()
    return wordsList


  def shift_computePlaintext(wlist, c):

    index = 0
    while index < 26:
        newCipher = shift_encrypt(index, c)
        print 'The new cipher text is: ', newCipher
        wordlistLen = len(wlist)
        i = 0
        while i < wordlistLen:
            print wlist[i]
            if newCipher == wlist[i]:
                return newCipher
            else:
                print 'Word not found.'
            i = i + 1
        index = index + 1    

   print 'Take Ciphertext and Find Plaintext from Wordlist Function: \n'
   list = wordList('test.txt')
   print list
   plainText = shift_computePlaintext(list, 'vium')
   print 'The plaintext was found in the wordlist: ', plainText

When the shift amount = 18, the ciphertext = name which is a word in my wordlist, but it never evaluates to True. Thanks for any help in advance!!

4

1 に答える 1

5

これまでの情報では断言できませんが、以下のように推測できます。

wordsList = fileObject.readlines()

これは、次listのように、改行が保持された一連の文字列を返します。

['hello\n', 'my\n', 'name\n', 'is\n', 'jesi\n']

したがって、 の内部で、復号化された に一致するものを探してshift_computePlaintext繰り返すと、 に一致する文字列を探していますが、 を含め、どれも一致しません。wlist'vium''name''name\n'

言い換えれば、まさにあなたが疑ったものです。

これを修正する方法はいくつかありますが、最も明白な方法は、 のwlist[i].strip()代わりにを使用するか、 の代わりに のwlist[i]ようなものを使用して最初からすべてを削除することです。wordsList = [line.strip() for line in fileObject]wordsList = fileObject.readlines()


いくつかの補足事項:

電話する正当な理由はほとんどありませんreadlines()。これは、繰り返し処理できる行のリストを返しますが、ファイル オブジェクト自体は、繰り返し処理できる行の反復可能オブジェクトでした。他の種類のイテラブルではなくリストであることを本当に確認する必要がある場合、または後で別のコピーを作成する必要があるlist場合などは、他のイテラブルの場合と同様に、それを呼び出すだけです。

次のようなループを書くことはほとんどありません。

index = 0
while index < 26:
    # ...
    index = index + 1

代わりに、次のようにします。

for index in range(26):

読みやすく、間違いにくくなっています (わずかな 1 つずつずれているエラーが、人生で行うイライラするデバッグの半分の原因となっています)、などです。

また、コレクションの長さをループしている場合でも、そうしないでください。これの代わりに:

wordlistLen = len(wlist)
i = 0
while i < wordlistLen:
    # ...
    word = wlist[i]
    # ...
    i = i + 1

…これを行うだけです:

for word in wlist:

…または、両方が必要な場合(ときどきi行いwordます):

for i, word in enumerate(wlist):

一方、コレクションをループする唯一の理由が各値をチェックすることである場合は、その必要さえありません。これの代わりに:

wordlistLen = len(wlist)
while i < wordlistLen:
    print wlist[i]
    if newCipher == wlist[i]:
        return newCipher
    else:
        print 'Word not found.'
    i = i + 1

…これを行うだけです:

if newCipher in wlist:
    return newCipher
else:
    print 'Word not found.'

ここで、実際には微妙なバグの 1 つが発生しています。見つからなかった場合に最後に 1 回だけ出力するのではなく、「Word not found」を何度も出力します。

于 2013-03-29T23:22:10.663 に答える