Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import random
- # длина блока кодирования
- CHUNK_LENGTH = 26
- # проверка длины блока
- #assert not CHUNK_LENGTH % 8, 'Длина блока должна быть кратна 8'
- # вычисление контрольных бит
- CHECK_BITS = [i for i in range(1, CHUNK_LENGTH + 1) if not i & (i - 1)]
- LEN_CHECK_BITS = len(CHECK_BITS)
- def chars_to_bin(chars):
- """
- Преобразование символов в бинарный формат
- """
- #assert not len(chars) * 8 % CHUNK_LENGTH, 'Длина кодируемых данных должна быть кратна длине блока кодирования'
- return ''.join([bin(ord(c))[2:].zfill(8) for c in chars])
- def octet_to_bin(octet):
- return ''.join(bin(int(octet))[2:].zfill(8))
- def bin_text_to_octet_list(bin_text):
- answer = []
- for octet in chunk_iterator(bin_text, 8):
- answer.append(int(octet, 2))
- return answer
- def chunk_iterator(text_bin, chunk_size=CHUNK_LENGTH):
- """
- Поблочный вывод бинарных данных
- """
- for i in range(len(text_bin)):
- if not i % chunk_size:
- yield text_bin[i:i + chunk_size]
- def get_check_bits_data(value_bin):
- """
- Получение информации о контрольных битах из бинарного блока данных
- """
- check_bits_count_map = {k: 0 for k in CHECK_BITS}
- for index, value in enumerate(value_bin, 1):
- if int(value) != 0:
- bin_char_list = list(bin(index)[2:].zfill(8))
- bin_char_list.reverse()
- bin_char_list = bin_char_list[:LEN_CHECK_BITS]
- for degree in [2 ** int(i) for i, x in enumerate(bin_char_list) if int(x) != 0]:
- check_bits_count_map[degree] += 1
- check_bits_value_map = {}
- for check_bit, count in check_bits_count_map.items():
- check_bits_value_map[check_bit] = 0 if not count % 2 else 1
- return check_bits_value_map
- def set_empty_check_bits(value_bin):
- """
- Добавить в бинарный блок "пустые" контрольные биты
- """
- for bit in CHECK_BITS:
- value_bin = value_bin[:bit - 1] + '0' + value_bin[bit - 1:]
- return value_bin
- def set_check_bits(value_bin):
- """
- Установить значения контрольных бит
- """
- value_bin = set_empty_check_bits(value_bin)
- check_bits_data = get_check_bits_data(value_bin)
- for check_bit, bit_value in check_bits_data.items():
- value_bin = '{0}{1}{2}'.format(value_bin[:check_bit - 1], bit_value, value_bin[check_bit:])
- return value_bin
- def get_check_bits(value_bin):
- """
- Получить информацию о контрольных битах из блока бинарных данных
- """
- check_bits = {}
- for index, value in enumerate(value_bin, 1):
- if index in CHECK_BITS:
- check_bits[index] = int(value)
- return check_bits
- def exclude_check_bits(value_bin):
- """
- Исключить информацию о контрольных битах из блока бинарных данных
- """
- clean_value_bin = ''
- for index, char_bin in enumerate(list(value_bin), 1):
- if index not in CHECK_BITS:
- clean_value_bin += char_bin
- return clean_value_bin
- def set_errors(encoded):
- """
- Допустить ошибку в блоках бинарных данных
- """
- result = ''
- for chunk in chunk_iterator(encoded, CHUNK_LENGTH + len(CHECK_BITS)):
- num_bit = random.randint(1, len(chunk))
- chunk = '{0}{1}{2}'.format(chunk[:num_bit - 1], int(chunk[num_bit - 1]) ^ 1, chunk[num_bit:])
- result += (chunk)
- return result
- def check_and_fix_error(encoded_chunk):
- """
- Проверка и исправление ошибки в блоке бинарных данных
- """
- check_bits = get_check_bits_data(encoded_chunk)
- error_index = sum([x for x in check_bits.keys() if check_bits[x] != 0])
- if error_index:
- encoded_chunk = '{0}{1}{2}'.format(encoded_chunk[:error_index - 1], int(encoded_chunk[error_index - 1]) ^ 1, encoded_chunk[error_index:])
- return encoded_chunk
- def get_diff_index_list(value_bin1, value_bin2):
- """
- Получить список индексов различающихся битов
- """
- diff_index_list = []
- for index, char_bin_items in enumerate(zip(list(value_bin1), list(value_bin2)), 1):
- if char_bin_items[0] != char_bin_items[1]:
- diff_index_list.append(index)
- return diff_index_list
- def encode_binary(text_bin):
- result = ''
- for chunk_bin in chunk_iterator(text_bin):
- chunk_bin = set_check_bits(chunk_bin)
- result += chunk_bin[::-1]
- return result
- def encode(source):
- """
- Кодирование данных
- """
- text_bin = chars_to_bin(source)
- while len(text_bin) % CHUNK_LENGTH != 0:
- text_bin += '0'
- return encode_binary(text_bin)
- def decode(encoded, fix_errors=True):
- """
- Декодирование данных
- """
- decoded_value = ''
- fixed_encoded_list = []
- for encoded_chunk in chunk_iterator(encoded, CHUNK_LENGTH + len(CHECK_BITS)):
- if fix_errors:
- encoded_chunk = check_and_fix_error(encoded_chunk[::-1])
- fixed_encoded_list.append(encoded_chunk)
- clean_chunk_list = []
- for encoded_chunk in fixed_encoded_list:
- encoded_chunk = exclude_check_bits(encoded_chunk)
- clean_chunk_list.append(encoded_chunk)
- clear_text = ''.join(clean_chunk_list)
- for clean_char in [clear_text[i:i + 8] for i in range(len(clear_text)) if not i % 8]:
- decoded_value += chr(int(clean_char, 2))
- return decoded_value
- def gui():
- source = input('Укажите текст для кодирования/декодирования:')
- print('Длина блока кодирования: {0}'.format(CHUNK_LENGTH))
- print('Контрольные биты: {0}'.format(CHECK_BITS))
- encoded = encode(source)
- octet_list = bin_text_to_octet_list(encoded)
- print('Закодированные данные: {0}'.format(encoded))
- print(sum(map(int, list(encoded))))
- while len(encoded) % CHUNK_LENGTH != 0:
- encoded += '0'
- decoded = decode(encoded)
- print('Результат декодирования: {0}'.format(decoded))
- encoded_with_error = set_errors(encoded)
- print('Допускаем ошибки в закодированных данных: {0}'.format(encoded_with_error))
- diff_index_list = get_diff_index_list(encoded, encoded_with_error)
- print('Допущены ошибки в битах: {0}'.format(diff_index_list))
- decoded = decode(encoded_with_error, fix_errors=False)
- print('Результат декодирования ошибочных данных без исправления ошибок: {0}'.format(decoded))
- decoded = decode(encoded_with_error)
- print('Результат декодирования ошибочных данных с исправлением ошибок: {0}'.format(decoded))
- def task_solver():
- octets = [130, 41, 86, 38, 143, 145, 32, 150, 196, 206, 68, 82, 32, 104, 112, 161, 80, 27, 77, 88, 208, 204, 1, 12, 76, 140, 2, 94, 2, 35, 7, 0, 191, 129, 64];
- text_bin = ''.join([octet_to_bin(x) for x in octets])
- while len(text_bin) % CHUNK_LENGTH != 0:
- text_bin += '0'
- decoded = decode(text_bin, fix_errors=True)
- print(decoded)
- if __name__ == '__main__':
- task_solver()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement