Kортежи и символы ascii в Python

AndreUT

Добрый день. Дело в том, что я криптограф, и в одной лабораторной столкнулся со следующей проблемой: - у нас имеется файл 1.TXT с шифртекстом кириллицей (кодировку файла я сразу ставлю ASCII), используется алгоритм афинной подстановки, но это не суть важно - нужно считывать из этого файла по два символа и выполнять над ними определенные действия - буквы в алфавите нашего ШТ, да и ОТ тоже, имеют чуть не такую нумерацию, как в алфавите (исключены несколько букв), посему я решил создать кортеж с элементами {символ : число}, а также кортеж, с элементами типа {число : символ}
# -*- coding: cp1251 -*-
import os
size = os.path.getsize("1.TXT")
key_num =  {'а' : 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,'ь' : 26,'ы' : 27,'э' : 28, 'ю' : 29, 'я' : 30}
num_key =  {'0': 'а', '1' : 'б', '2' : 'в', '3' : 'г', '4' : 'д', '5' : 'е', '6' : 'ж','7' : 'з','8' : 'и','8' : 'й','10' : 'к','11' : 'л','12' : 'м','13' : 'н','14' : 'о','15' : 'п','16' : 'р','17' : 'с','18' : 'т','19' : 'у','20' : 'ф','21' : 'х','22' : 'ц','23' : 'ч','24' : 'ш','25' : 'щ','26' : 'ь','27' : 'ы','28' : 'э','29' : 'ю','30' : 'я'}
s = ''
f = open("1.TXT", "r")
for i in range(0,size-1):
    ch0 = f.read(1)
    ch1 = f.read(1)
    i += 1
    d_b = 42*(int(key_num.get(ch0))*42+int(key_num.get(ch1))-885)%961
    s = chr(d_b/31)+chr(d_b%31)
print s
Проблема состоит из двух пунктов: 1. Когда я запускаю программу, то выдается сообщение типа "int() argument must be a string or a number, not 'NoneType' " 2. Когда я пишу что-то типа:
print num_key.get('0')
, то выводится не символ "а", а буква "р", если в скобках указать не ноль, а один, то выводится "с" и т.д.
4 ответа

AndreUT

посему я решил создать кортеж с элементами {символ : число}, а также кортеж, с элементами типа {число : символ}
Это не кортеж (tuple), а словарь (dict). Кортеж - это тот, который в круглых скобках.Советую сделать ключами словаря num_key числа, а не строки. Вообще в программе проблемы с типами данных. Значения в key_num и так целые числа, а вы их ещё раз преобразуете с помощью int.
Когда я запускаю программу, то выдается сообщение типа "int() argument must be a string or a number, not 'NoneType' "
None возвращает метод get, когда вы пытаетесь получить несуществующий элемент. И зачем вы используете get? Вместо key_num.get(ch0) можно писать key_num[ch0]Да и вообще, решение с двумя словарями плохое.Последняя же проблема, как мне кажется, из-за неправильного считывания файла. Оно сделано ужасно. Использование os.path.getsize вообще убило. Я бы вам написал как нормально, но формат входного файла я не знаю (можете скинуть пример).В восьмой строке, кстати, первый аргумент у range не нужен.


AndreUT

спасибо большое ))входной файл - набор кириллических символов. вот начало (первые две строчки):
лквдвдьышкрбызякиабшачрнвязарчтчлчькзтманэмнязяыбштрпнхтрхрнзтжккысечамнмпывйвфяжтинфвйвйвсжнпчнмпгу ****************************************************************************************************
там еще оказывается '\n', их надо бы пропускать, но это я сделаю )) я не знаю, как именно сделать считывание, чтоб символы выводились именно те, что в файле ))


AndreUT

AndreUT, я не очень понял, что делается со считываемыми символами. Кстати, здесь ещё одна ошибка: у вас в строке 13 после считывания каждой пары символов и выполнения преобразований выводимая строка s переопределяется заново (там, думаю, нужно заменить = на += ).Вот, это пример считывания попарно двух символов, игнорируя '\n':
for line in open('1.txt'):
    line = line.rstrip()
    for index, ch0 in list(enumerate(line))[::2]:
        ch1 =  line[index + 1]
        # Теперь ch0 и ch1 - ваши символы, делайте с ними всё, что хотите
Объясню значение некоторых сложных моментов: Строка 1. Делаем цикл по итератору открытого файла. Это значит, что: а). Файл открывается; б). Запускается цикл, где на каждом проходе (итерации) считывается по строке line; в). После завершения цикла файл закрывается сам (по-хорошему это надо делать, но у вас этого не было). Строка 2. Для строки line применяем метод rstrip, обрезающий символы типа \r и \n справа. Строка 3. Запускаем ещё один цикл по преобразованной строке line. Например, вот поэтапно эти преобразования для строки 'qwerty':
>>> line = 'qwerty'
>>> enumerate(line)
<enumerate object at 0xb7793c0c>
>>> list(enumerate(line))
[(0, 'q'), (1, 'w'), (2, 'e'), (3, 'r'), (4, 't'), (5, 'y')]
>>> list(enumerate(line))[::2] # Оставляем только символы с нечётными индексами: 0, 2, 4, ...
[(0, 'q'), (2, 'e'), (4, 't')]
Далее цикл проходится по получившемуся объекту, и на каждой итерации index будет равняться числам от 0 до 5 (для данного примера) - индексу символа в строке, а ch0 - этому самому символу. Строка 4. ch1 приравнивается к символу, следующему за ch0, исходя из индекса ch0.Так получается, что ch0 и ch1 - поочерёдные пары подряд идущих символов из файла.


AndreUT

спасибо! дело в том, что нужно считывать скорее по два символа (пропуская служебные символы и т.д.), а не построчно, потому что у меня каждой биграмме соответствует биграмма открытого текста, а со строками может быть ситуация, в которой один символ биграммы в одной строке, а другой - в следующейпрошу прощенья, в каждой строчке по 100 символов, я проверил только что )) я попробую сделать так, как вы советуете ) спасибо вам!