Помогите разобраться с ответом от сервера codewars.com!
Решаю вот такую ката с сайта
https://www.codewars.com/kata/5ef9ca8b76be6d001d5e1c3e/train/python
Она называется Error correction #1 - Hamming Code === Исправление ошибок # 1 - Код Хэмминга Код Хэмминга используется для исправления ошибок, так называемых переворотов битов, при передаче данных. Далее в описании следует подробное объяснение того, как это работает. В этом Кате мы реализуем код Хэмминга с длиной в 3 бита;
Задача 1: функция кодирования
Реализуйте функцию кодирования, выполнив следующие шаги:
преобразовать каждую букву текста в ее значение ASCII; преобразовать
значения ASCII в 8-битные двоичные файлы; утроить каждый бит;
объединить результат
input: "hey" --> 104, 101, 121 // ASCII values --> 01101000, 01100101, 01111001 // binary --> 000111111000111000000000 000111111000000111000111 000111111111111000000111 // tripled --> "000111111000111000000000000111111000000111000111000111111111111000000111" // concatenated
Задача 2: функция декодирования:
Проверьте, не возникли ли ошибки, и исправьте их. Ошибками будут только перевороты битов, а не потеря битов:
111 -> 101: это может и случится 111 -> 11: этого не может быть
Примечание: длина входной строки также всегда делится на 24, так что вы можете преобразовать ее в значение ASCII.
Шаги:
Разделите ввод на группы по три символа;
Проверьте, не произошла ли ошибка: замените каждую группу символом, который встречается чаще всего, например 010 -> 0, 110 -> 1 и т. Д .;
Возьмите каждую группу из 8 символов и преобразуйте это двоичное число;
Преобразуйте двоичные значения в десятичные (ASCII);
Преобразуйте значения ASCII в символы и объедините результат
input: "100111111000111001000010000111111000000111001111000111110110111000010111" --> 100, 111, 111, 000, 111, 001, ... // triples --> 0, 1, 1, 0, 1, 0, ... // corrected bits --> 01101000, 01100101, 01111001 // bytes --> 104, 101, 121 // ASCII values --> "hey"
Вот мои две функции:
import re
from string import digits
from string import punctuation
from string import whitespace
def encode(string):
lst = []
for el in string:
if el in punctuation or el in digits or el in whitespace: # add 1 bit
lst.append(bin(ord(el)).replace('b', '0'))
else:
lst.append(bin(ord(el)).replace('b', ''))
K = []
for st in lst:
for chars in st:
K.append(chars*3) # triple the beats
bits = ''.join(K)
return bits # get a concatenated string of triple bits
def decode(bits):
binary = re.sub(r'(\d{3})', r'\1 ', bits)
binary = binary.replace('000', '0').replace('111', '1').replace(' ', '')
binary = re.sub(r'(\d{8})', r'\1 ', binary)
binary = binary.split()
lst = []
for bi in binary:
lst.append(int(bi, 2))
string = ''
for el in lst:
string += chr(el)
return string
Вот ответ от проверочного сервера:
Passed: 204 Failed: 104 Exit Code: 1
Test encode function ======================> я прохожу
Test decode function ==================> у меня не проходит
Should work with short word
'\x9aI\x93v%' should equal 'hey'
Completed in 0.37ms
Should work with long word
'U\x1a&U!\x14Ù[\x9cÚV\x92\x07FöÆD\x82me thb]\x12\x06\x92\x066\x16â\t\x91½ this kata' should equal 'The Sensei told me that i can do this kata'
У меня установлена ОС на базе ядра Linux Ubuntu 20.04.1 Программирую в Thonny(мне кажется тут самый лучший и понятный отладчик) Самое главное в том что у меня в редакторе все получается и кодирование(получение битовой сконкатенированной строки) и декодирование(вставляю сконкатенированную битовую строку) === получаю строку ASCII
вот эта строка у меня в редакторе и кодируется и декодируется кодом Хемминга:
The Sensei told me that i can do this kata
а вот такую "байду" присылает сервер:
U\x1a&U!\x14Ù[\x9cÚV\x92\x07FöÆD\x82me thb]\x12\x06\x92\x066\x16â\t\x91½ this kata
Кто может, ПОЖАЛУЙСТА! объясните почему так происходит!
Ответы (3 шт):
Я решил её так:
hamm = {'000': '0','001': '0','010': '0','011': '1','100': '0','101': '1','110': '1','111': '1'}
def chunked_str(s, sz):
return (s[i:i+sz] for i in range(0, len(s), sz))
def encode(string):
return ''.join(3*bit for char in string for bit in format(ord(char), '08b'))
def decode(bits):
repaired = ''.join(hamm[triplet] for triplet in chunked_str(bits, 3))
return ''.join(chr(int(byte, 2)) for byte in chunked_str(repaired, 8))
У вас не было исправления ошибок в тройках битов, это когда выбирается тот бит, который встречается чаще.
Ваш код с регулярками получился симпотичным, единственная проблема, что вы схлопывали тройки одинаковых битов, а нужно было из них выбрать тот бит, что чаще встречается.
Пример выбора бита из троек (тут не имеет значение какой порядок битов):
- 110 или 111 -> 1 (сумма битов 2 или 3)
- 001 или 000 -> 0 (сумма битов 0 или 1)
Я исправил вашу функцию, попробуйте:
def decode(bits):
binary = ''
for tripled_bits in re.findall(r'\d{3}', bits):
sums = sum(map(int, tripled_bits))
binary += '1' if sums == 2 or sums == 3 else '0'
text = ''
for byte in re.findall(r'\d{8}', binary):
text += chr(int(byte, 2))
return text
PS.
Интересное задание :)
А у меня получилось так:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i: i + n]
def encode(text: str) -> str:
return ''.join(
''.join(b * 3 for b in f"{ord(c):08b}") # Tripled bits
for c in text
)
def decode(bits: str) -> str:
bit_items = []
for tripled_bits in chunks(bits, 3):
sums = sum(map(int, tripled_bits))
# Example: 110 or 111 -> 1 and 000 -> 0 or 001 -> 0
bit_items.append('1' if sums == 2 or sums == 3 else '0')
binary = ''.join(bit_items)
items = []
for byte in chunks(binary, 8):
items.append(chr(int(byte, 2)))
return ''.join(items)
Проблема не в ответе от сервера.
Просто вы не до конца поняли задачу.
С пониманием encode проблем у вас вроде нет (хотя код переусложнили)
А вот с decode проблемы.
Проверьте, не возникли ли ошибки, и исправьте их.
Этот этап полностью пропущен.
Смысл задачи — коррекция ошибок. В каждом триплете входной последовательности один из трёх бит может быть неправильным. Перед декодированием вам нужно выяснить, каких бит в триплете больше и использовать его.
Проще и производительнее всего завести словарь замен с восемью вхождениями.
{'000': '0','001': '0','010': '0','011': '1','100': '0','101': '1','110': '1','111': '1'}