情報学部大学生のダラダラ日記

β日記

機械学習や日記っぽいものを書きます

言語処理100本ノック2020 第1章 Pythonでの解答例

スポンサーリンク

はじめに

夏休みに入り、研究室のゼミも少なくなったりコ〇ナの影響でバイトがなくなったりして暇なので1日1個言語処理100本ノックを第3章までやりたいと思います。第3章までとしているのは、とりあえずデータの前処理を再勉強したいということと短期的な目標としたいからです。8月5日から始めるので順当にいけば9月3日に終わります。しかし、僕のことなので途中で飽きてサボってしまったり、辞めてしまったりするかもしれません。というか多分なります。1週間続けば自分としては立派だと思います。統計学入門も終わってないし…。

nlp100.github.io

毎日別の記事として投稿すると記事数がとても多くなってしまうので各章ごと(全10章)記事として保存します。各章が終わるまで同一の記事に更新していこうと思います。更新する度タイトルの〇日目も変えます。

第1章:事前準備

nlp100.github.io

00.文字列の逆順(1日目|8月5日)

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

2通りのやり方で解きました。1つ目はreversed()を用いて逆順にし、リスト化した後に結合する方法です。2つ目はスライシングによって直接逆順にします。a[::-1]は"最初から最後まで逆順に1つずつ抜き出す"という意味です。2つ目の方が簡単ですね。

 

01.パタトクカシーー(2日目|8月6日)

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

00と同様、スライシングで解く手法が最も楽です。たまたま今回は1,3,5,7となっているため、[::2](最初から最後まで2つおきに)とすることで実装することができましたが、1,2,4,6,9…番目を取り出せという問題でも対応することが可能なように泥臭い手法も書いておきました。

02. 「パトカー」+「タクシー」=「パタトクカシーー」(3日目|8月7日)

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

 for文で複数のイテラブルオブジェクトを取得するためにzip()関数を使います。iにパトカー、jにタクシーがそれぞれ入ります。ans_1とans_2を用意しましたが、ans_1はリスト内包表記をとっているので見慣れていない方は何をやっているのかわかりにくいかな、と思ったのでans_2で少し冗長な導出をしました。どちらもやっていることは変わりません。リスト内包表記を簡単に説明すると、[式 for 変数 in リスト等]となります。ans_2にもある通り、これはfor 変数 in リスト等: リスト.append(式)と同じ意味です。

03.円周率(4日目|8月8日)

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

方針としてはまず単語ごとにリストに格納します。しかしこの時","や"."があると文字数がおかしくなるのでこれらを削除します。replace()は第1引数を第2引数に置換します。なので本プログラムのように書くと削除することが可能です。今回、2文字削除したいため2回replace()しています。削除したい文字がより多くなるのならば正規表現によって削除するやり方もあるようなのでそちらにしましょう。リストに格納した後はリストの各要素の長さ(=単語の文字数)を取得します。今回もリスト内包表記を取っています。iに_listに入っている各単語が入り、iの長さを取っています。

04.元素記号(5日目|8月9日)

“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文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ. 

今回は辞書型を作成します。01.のように規則的に取り出す対象が並んでいないので対象のインデックス番号のリストを作成します。 enumerate()は2つの変数に値を入れていきます。1つ目にはインデックス番号、2つ目には対象オブジェクト(リスト等)の中身です。対象の単語ならば1文字目([0])、そうでないならば2文字目まで([:2]=0,1)を取り出し辞書へ格納します。

05.n-gram(6日目|8月10日)

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

n-gramとはある文字列をn個の単語や文字で区切ることを言います。ここで問題になっているbi-gramは2-gramです。関数自体は単純なもので引数として受け取ったn-gramのn個ごと文章の最初から区切っているだけです。

06.集合(7日目|8月11日)

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

まずbi-gramを作成します。05で作成した関数をimportで呼び出します。ファイル名を05.pyとしてので直接importせず、__import__()によって呼び出します。詳しくは以下に書きました。

parco1021.hatenablog.com

そのままだと重複する要素('pa'など)があるため集合として機能しません。そのためset()を用いることで重複する要素を消し、集合演算を行うことのできるようにします。その後は各集合に演算子やメソッドが用意されているのでそれを使うだけです。今回、例として両方とも使っています。'se'があるかどうかはin演算子を使い確認します。

07.テンプレートによる文生成(8日目|8月12日)

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

format()メソッドによって文字列内に変数を入れます。あとは特に説明することはないです。

08.暗号文(9日目|8月13日)

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

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

問題文の219が何かわからなかったので英小文字の文字コードをまず調べます。文字コードはord()によって調べることが可能です。"a"が97、"z"が122なので97+122=219となります。つまりa→z、z→aのように暗号化、復号化をします。文字コードから文字への変換はchr()を使います。英小文字か否かの判定はislower()を使います。英小文字ならば暗号、復号化を行いそれ以外だったらそのままにします。結果を見ると大文字の"I"と"."がそのまま出力されており、復号化もできていることがわかります。

09.TypoglycemiaPermalink(10日目|8月14日)

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

入力を単語とする関数typo()を作ります。受け取った単語の長さが5以上ならば(元の単語の1文字目)+(真ん中をシャッフル)+(元の単語の最後)のリストを作り、join()で結合したものを返します。

これで第1章は終わりです。

第2章↓↓

parco1021.hatenablog.com

スポンサーリンク