毎朝ちびちびCodewars。
Decode the Morse Code, advanced [4級] https://www.codewars.com/kata/decode-the-morse-code-advanced/
今日のお題:
""" モールス信号デコーダー2 - ビットレートが異なるデジタル信号からのデコード 新たに書く関数decodeBits(bits) で デジタル信号を'.(ドット)'と '-(ハイフン)' からなる モールス信号までデコードする。それを、 (前回のチャレンジ)[https://acokikoy.hatenablog.com/entry/2019/05/05/223341]で書いた decodeMorse(morseCode)関数に受け渡し、人が理解できるメッセージ文へとデコードする。 decodeBits(bits): Args: bits (str): デジタル信号 - "Dot" – 1 unit時間分の'1' - "Dash" – 3 unit時間分の'1' - ビット間の区切り - 1 unit時間分の'0' - 文字間の区切り - 3 unit時間分の'0' - 単語間の区切り - 7 unit時間分の'0' Returns: '.(ドット)'と '-(ハイフン)' ’ (スペース)' からなるモールス信号(str) """
コード
me
# Decode the Morse Code, advanced [4級] # https://www.codewars.com/kata/decode-the-morse-code-advanced/ def decodeBits(bits): # ToDo: Accept 0's and 1's, return dots, dashes and spaces bits = bits.strip('0') unit = len(sorted(set(bits.split('1') + bits.split('0')) - {''}, key = len)[0]) return bits.replace('111'*unit, '-').replace('1'*unit, '.').replace('0000000'*unit, ' ').replace('000'*unit, ' ').replace('0'*unit, '') def decodeMorse(morseCode): # ToDo: Accept dots, dashes and spaces, return human-readable message morse_list = morseCode.strip().replace(' ', ' # ').split() message = '' for m in morse_list: if m == '#': message += ' ' else: message += MORSE_CODE[m] return message
- ビットレートは毎回異なるので、これを求めるところがポイント。
- 信号1単位分の長さをunitとすると、 unit = 連続する'0' ないし'1'の、最短長
ビットレート(unit)がわかれば、あとはbitsを長いパターンから順に変換することでモールス信号が求まる。
'111' * unit => '-' '1' * unit => '.' '0000000' * unit => wordの区切り' ' '000' * unit => letterの区切り' ' '0' * unit => 信号の区切り(削除)
- 最初書いた流れでsetを使っているが、sorted(key=len)で文字長比較するなら、わざわざsetを使って要素を減らす必要はなかったかも。
文法、関数・メソッドnote
sorted(iterable, *, key=None, reverse=False)
https://docs.python.org/ja/3/library/functions.html#sorted
- iterable の要素を並べ替えた新たなリストを返す。
- setにも使える
- 「key=len」とすると比較対象が len(各要素) になる。
b0 = sorted(set(bits.split('1')) - {''}) b1 = sorted(set(bits.split('0')) - {''}) unit = len(b1[0]) if b0==[] or len(b1[0]) <= len(b0[0]) else len(b0[0])
最初は上記のように書いていたのが、keyを使うことで ↓ こうなる
unit = len(sorted(set(bits.split('1') + bits.split('0')) - {''}, key = len)[0])