LoginSignup
17
20

言語処理100本ノック2020 (00~09)

Last updated at Posted at 2023-10-20

はじめに

本記事は言語処理100本ノックの解説です。
100本のノックを全てこなした記録をQiitaに残します。
使用言語はPythonです。

今回は第1章:準備運動(00~09)までの解答例をご紹介します。

00. 文字列の逆順

文字列”stressed”の文字を逆に(末尾から先頭に向かって)並べた文字列を得よ.

コード
text00 = "stressed"
temp = ""
for i in reversed(text00):
    temp += i
print(temp)

# こっちの方がスマート。。
# text00[::-1]
出力結果
desserts

コメント
スライスの問題。他の解説記事と同じになるので最初に思いついたのを記載。

01. 「パタトクカシーー」

「パタトクカシーー」という文字列の1,3,5,7文字目を取り出して連結した文字列を得よ.

コード
text01 = "パタトクカシーー"
temp = ""
for i, ch in enumerate(text01):
    if i % 2 == 1:
        continue
    else:
        temp += ch
print(temp)

# こっちの方がスマート。。。
#text01[::2]
出力結果
パトカー

コメント
これもスライスの問題。00に同じく最初に思いついた解法を記載。プログラミングの授業の課題で出てきそう。

02.「パトカー」+「タクシー」=「パタトクカシーー」

「パトカー」+「タクシー」の文字を先頭から交互に連結して文字列「パタトクカシーー」を得よ.

コード
text02a = "パトカー"
text02b = "タクシー"
temp = ""
for t0, t1 in zip(text02a, text02b):
    temp += t0
    temp += t1
print(temp)
出力結果
パタトクカシーー

コメント
zipは同時に回せていいよね。パタトクカシーーの元ネタはピタゴラスイッチとのこと。

03. 円周率

“Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.”という文を単語に分解し,各単語の(アルファベットの)文字数を先頭から出現順に並べたリストを作成せよ.

コード
text03 = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
num_list = []
temp = ""
text03 = text03.replace(",", "")
for ch in text03:
    if ch == " " or ch == ".":
        num_list.append(len(temp))
        temp = ""
    else:
        temp += ch
print(num_list)
出力結果
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

コメント
「,」や「.」の処理がポイント。もっとイケてる書き方あるなと思いつつ放置。

04. 元素記号

“Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.”という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭の2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.

コード
dict04 = {}
text04 = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
text04 = text04.replace(".", "")
list04 = text04.split(" ")
num_list = {1, 5, 6, 7, 8, 9, 15, 16, 19}
for i, atom in enumerate(list04, 1):
    if i not in num_list:
        temp = atom[:2]
        dict04[temp] = i
    else:
        temp = atom[0]
        dict04[temp] = i
print(dict04)
出力結果
{'H': 1, 'He': 2, 'Li': 3, 'Be': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'Ne': 10, 'Na': 11, 'Mi': 12, 'Al': 13, 'Si': 14, 'P': 15, 'S': 16, 'Cl': 17, 'Ar': 18, 'K': 19, 'Ca': 20}

コメント
よくこの文章を思いついたなと感心。

05. n-gram

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数を作成せよ.この関数を用い,”I am an NLPer”という文から単語bi-gram,文字bi-gramを得よ

コード
def N_gram(n, text):
    char = text.replace(" ", "")
    word = text.split(" ")
    char_list = []
    word_list = []
    for ch in range(len(char)):
        char_list.append(char[ch:n+ch])
    for wch in range(len(word)):
        word_list.append(word[wch:n+wch])
    return char_list, word_list

c, w = N_gram(2, "I am an NLPer")
print("文字bi-gram",c)
print("単語bi-gram",w)
出力結果
文字bi-gram ['Ia', 'am', 'ma', 'an', 'nN', 'NL', 'LP', 'Pe', 'er', 'r']
単語bi-gram [['I', 'am'], ['am', 'an'], ['an', 'NLPer'], ['NLPer']]

コメント
n-gramとか自然言語処理ぽくなってきたなと感じた。「NLPer」は、自然言語処理の研究者や開発者を指す言葉らしいです。

06. 集合

“paraparaparadise”と”paragraph”に含まれる文字bi-gramの集合を,それぞれ, XとYとして求め,XとYの和集合,積集合,差集合を求めよ.さらに,’se’というbi-gramがXおよびYに含まれるかどうかを調べよ.

コード
text6a = "paraparaparadise"
text6b = "paragraph"
A_bi, _ = N_gram(2, text6a)# 05.n-gramで使った関数
B_bi, _ = N_gram(2, text6b)# 05.n-gramで使った関数
X = set(A_bi)
Y = set(B_bi)
print("和集合: ", X | Y)
print("積集合: ", X & Y)
print("差集合: ", X - Y)

checkword = "se"
if checkword in X and checkword in Y:
  print("XとYにが{}含まれる".format(checkword))
elif checkword in X:
  print("Xに{}が含まれる".format(checkword))
elif checkword in Y:
  print("Yに{}が含まれる".format(checkword))
else:
  print("{}はXとYには含まれない".format(checkword))
出力結果
和集合:  {'gr', 'h', 'ad', 'ap', 'pa', 'is', 'ag', 'ra', 'ar', 'ph', 'e', 'di', 'se'}
積集合:  {'ap', 'pa', 'ra', 'ar'}
差集合:  {'ad', 'is', 'e', 'di', 'se'}
Xにseが含まれる

コメント
setは便利。それだけ。

07. テンプレートによる文生成

引数x, y, zを受け取り「x時のyはz」という文字列を返す関数を実装せよ.さらに,x=12, y=”気温”, z=22.4として,実行結果を確認せよ.

コード
def Template(x, y, z):
    temp = str(x)+ "時の" + str(y)+ "" + str(z)
    return temp

result = Template(12, "気温", 22.4)
print(result)
出力結果
12時の気温は22.4

コメント
変数の型についての知識があれば秒で終わる問題。

08. 暗号文

与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.

英小文字ならば(219 - 文字コード)の文字に置換
その他の文字はそのまま出力
この関数を用い,英語のメッセージを暗号化・復号化せよ.

コード
import re
def cipher(text):
    repatter = re.compile('[a-z]')
    temp = ""
    for ch in text:
        if re.match(repatter, ch):
            ch = chr(219 - ord(ch))
        temp += ch
    return temp

encode = cipher("the quick brown fox jumps over the lazy dog")
print("暗号化:",encode)
decode = cipher(encode)
print("復号化:",decode)
出力結果
暗号化: gsv jfrxp yildm ulc qfnkh levi gsv ozab wlt
復号化: the quick brown fox jumps over the lazy dog

コメント
暗号化に使った文章は、答え合わせのため本問の先駆者と同じものを使用。

09. Typoglycemia

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

コード
import random
text09 = "I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind ."
text09 = text09.replace(".", "")
text09b = text09.split(" ")
temp = ""
for txt in text09b:
    if len(txt) <= 4:
        pass
    else:
        txt = txt[0]+"".join(random.sample(txt[1:-1], len(txt[1:-1])))+txt[-1]
    temp += txt + " "
result = temp[:-1] + "."
print(result)
出力結果
I cluon’dt believe that I cuold aucllaty udsrntnaed what I was rndaieg : the poeannemhl pwoer of the hmaun mind .

コメント
タイポグリセミア(Typoglycemia)は、文章中のいくつかの単語で最初と最後の文字以外の順番が入れ替わっても正しく読めてしまう現象だそうです(wiki参照)。確かに読めないことはない?

他章の解答例

17
20
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
20