首页 > 解决方案 > 欧拉项目#59,错误答案

问题描述

我不知道为什么这段代码没有给出正确的答案

我在英特尔酷睿 i3 处理器上运行了这段代码

from array import array

with open("cipher.txt","r") as file:

    main_list=file.read().split(",")

sub_list1=array("i",[])

sub_list2=array("i",[])

sub_list3=array("i",[])

for i in range(len(main_list)):

    if i%3==0:

        sub_list1.append(int(main_list[i]))

    elif i%3==1:

        sub_list2.append(int(main_list[i]))

    else:

        sub_list3.append(int(main_list[i]))


def is_valid(xor):

     if 32 <= xor <= 90:

        return True

     elif 97 <= xor <= 122:

        return True

     return False


ASCIIs2=list(range(97,123))

_lists=[sub_list1,sub_list2,sub_list3]

codes=[]

while len(codes)!=len(main_list):

    for _list in _lists:

        for key in ASCIIs2:

            codes_copy=[]

            for value in _list:

                n=int(value)^key

                if is_valid(n) :

                    codes_copy.append(int(value)^key)

                else:

                    break

            else:

                codes+=codes_copy

                break


print(sum(codes)) 

根据答案,sub_list1 应该被 103 解密,但这表示它被 101 解密

标签: python-3.x

解决方案


您可以很容易地应用频率分析,而不是强制使用它。您知道密钥由三个小写字符组成,第一个字符编码为 text[0,3,...],第二个字符编码为 [1,4,...],第三个字符编码为 [2, 5,...]。将您的文本分成 3 部分,找到每个部分中最常用的数字,键将是最常用数字 ^ 英语中最常用字符的异或结果。

将密钥应用于文本,将明文转换为 ASCII 数字,求和并尝试挑战 60 :)

剧透警报:

  • 最常见的字符是''(空格)。
  • 关键跟欧拉有关……

下面的代码:

def decrypt(array,key):
    en = []
    j = 0
    for i in range(len(array)):
        en.append(chr(array[i]^int(ord(key[j]))))
        j+=1
        if j>2:
            j = 0
    en = ''.join(en)
    
    return en

def to_ascii(text):
    return [ord(c) for c in text]

def main():
    #read the crypted text
    f = open('cipher.txt')
    cipher = f.read().strip().split(',')
    f.close()

    #convert to int
    cipher = [int(x) for x in cipher]

    #cut in 3 parts
    c = []
    for i in range(3):
        c.append(cipher[i::3])

    #find the most used char in each / it should be ' '
    key = []

    for i in range(3):
        dic = {}
        for ch in c[i]:
            if ch in dic:
                dic[ch] +=1
            else:
                dic[ch] = 1

        #reverse the dic
        dic = {dic[k]:k for k in dic}
        crypted = max(dic.items())[1]
    
        #reverse the xor to get the key that makes the number = ' '
        key.append(chr(crypted^ord(' ')))

    key = ''.join(key)

    #decrypt / convert and sum
    return sum(to_ascii(decrypt(cipher,key)))

推荐阅读