MikiTech

文系新卒エンジニアの学習記録

【Python】言語処理100本ノック2020 09. Typoglycemia

問題

nlp100.github.io

スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)を与え,その実行結果を確認せよ.

環境

Macbook Pro Python3.7.7

ソースコード

GitHubを載せておきます。 github.com

'''
スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,
それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ.
ただし,長さが4以下の単語は並び替えないこととする.
適当な英語の文
(例えば”I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .”)
を与え,その実行結果を確認せよ.
'''
import random

'''
ランダムに複数の要素を選択(重複なし): random.sample()
randomモジュールの関数sample()で、リストからランダムで複数の要素を取得できる。要素の重複はなし(非復元抽出)。

第一引数にリスト、第二引数に取得したい要素の個数を指定する。リストが返される。
'''

def typoglycemia(word):
     if len(word) <= 4:
         return word
     else:
         text = random.sample(list(word[1:-1]),len(word[1:-1]))
         return ''.join([word[0]] + text + [word[-1]])


sentense = input("解答1の英文>>")
ans = [typoglycemia(word) for word in sentense.split()]

print('解答1の変換結果:' + ' '.join(ans))

'''
元のリストをシャッフル: random.shuffle()
randomモジュールの関数shuffle()で、元のリストをランダムに並び替えられる。
'''

#解答2
result = []
def Typoglycemia(target):
    for word in target.split(' '):
        if len(word) <= 4:
            result.append(word)
        else:
            chr_list = list(word[1:-1])
            random.shuffle(chr_list)
            result.append(word[0] + ''.join(chr_list) + word[-1])

    return ' '.join(result)

# 対象文字列の入力
target = input('解答2の英文--> ')

# タイポグリセミア
result = Typoglycemia(target)
print('解答2の変換結果:' + result)
'''
#出力イメージ
解答1の英文>>I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .
解答1の変換結果:I cdunl’ot bievlee that I could atclauly uedsanrntd what I was rianedg : the pmeeoannhl pwoer of the hmuan mind .
解答2の英文--> I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .
解答2の変換結果:I cndol’ut beievle that I cluod altaucly utdnanesrd what I was rednaig : the poanmneehl pweor of the hmaun mind .
'''

答え方が2つあるなと感じたので、それぞれ説明をしていきます。

考え方1

まずはrandomを使った答え方。
一番最初に思いつきやすいものかと思います。

import random

'''
ランダムに複数の要素を選択(重複なし): random.sample()
randomモジュールの関数sample()で、リストからランダムで複数の要素を取得できる。要素の重複はなし(非復元抽出)。

第一引数にリスト、第二引数に取得したい要素の個数を指定する。リストが返される。
'''

def typoglycemia(word):
     if len(word) <= 4:
         return word
     else:
         text = random.sample(list(word[1:-1]),len(word[1:-1]))
         return ''.join([word[0]] + text + [word[-1]])


sentense = input("解答1の英文>>")
ans = [typoglycemia(word) for word in sentense.split()]

print('解答1の変換結果:' + ' '.join(ans))

ここでは、randomモジュールのsampleメソッドを利用しています。

note.nkmk.me

sampleメソッドでは、第一引数に対象となるリスト、第二引数にそのリストからいくつランダムで取り出すのか?という数字を指定します。
戻り値はリストとなっています。

ここでは、まずコマンドラインで受け取った文をsplitでわけ、分けた単語をtypoglycemiaメソッドに引数として渡しています。
typoglycemiaメソッド内部では、まず4文字かどうかを条件分岐し、
そしてsampleメソッドで回しています。

sampleメソッドに渡す際には、 今回の問題では最初の文字と最後はいじらないとあるので、
スライスする際は[1:-1]と指定をしています。
リストが戻り値のため、 joinで文字列に挿入をしています。

以上が解答1になります。

考え方2

続いてshuffleを使った解答です。
基本はrandomと同じ(少し処理の書き方を変えています。)ですが、引数の指定が一つと単純に書くことができました。

'''
元のリストをシャッフル: random.shuffle()
randomモジュールの関数shuffle()で、元のリストをランダムに並び替えられる。
'''

#解答2
result = []
def Typoglycemia(target):
    for word in target.split(' '):
        if len(word) <= 4:
            result.append(word)
        else:
            chr_list = list(word[1:-1])
            random.shuffle(chr_list)
            result.append(word[0] + ' '.join(chr_list) + word[-1])

    return ' '.join(result)

# 対象文字列の入力
target = input('解答2の英文--> ')

# タイポグリセミア
result = Typoglycemia(target)
print('解答2の変換結果:' + result)

今度は、splitで分割する処理をメソッド内にしました。
ですが、基本的にrandomと処理は同じです。

最初と最後の文字は動かさないので、スライスは[1:-1]で指定。
shuffleメソッドは、引数に受け取ったリストの内部をランダムに並べ替えます

なので、[1:-1]でスライスした文字をリストにします。
そしてこれをshuffleメソッドに渡して並べ替えます。

それからリストを文字列として挿入、文字の最初と最後を付け加えたものをリストにキャスト変換。

またjoinで文字列に直していくという流れにしてみました。

よりよいメソッドや解答があればぜひ教えて下さい。