言語処理100本ノック 2015 2日目

  • 4
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

言語処理100本ノックを見つけたのでやる。環境はPython2.7 + Ubuntu15.10です。
いたらぬ点もありますがよろしくお願いします

もう解けてるやつ 00,01,03,07,08,10
まだ解けてないやつ たくさん

第1章: 準備運動

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

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

02.py
#coding: UTF-8

p = u'パトカー'
t = u'タクシー'

str = "".join(i+j for i,j in (zip(p,t)))
print str 

実行結果
haruka@ubuntu:~/NLP100$ python 02.py
パタトクカシーー

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

04.py
text = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."

num = [1,5,6,7,8,9,15,16,19]
dic = {}

for (i,x) in enumerate(text.split(),1):
  if i in num:
    dic[x[0:1]] = i
  else:
    dic[x[0:2]] = i

print dic

実行結果
haruka@ubuntu:~/NLP100$ python 04.py
{'Be': 4, 'C': 6, 'B': 5, 'Ca': 20, 'F': 9, 'S': 16, 'H': 1, 'K': 19, 'Al': 13, 'Mi': 12, 'Ne': 10, 'O': 8, 'Li': 3, 'P': 15, 'Si': 14, 'Ar': 18, 'Na': 11, 'N': 7, 'Cl': 17, 'He': 2}

05.n-gram

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

05.py
#coding: UTF-8
text = "I am an NLPer"

def ngram(text,n):
  list = []
  if len(text) >= n:
      for i in xrange(len(text) - n + 1):
          list.append(text[i:i+n])
  return list

print ngram(text,2)
print ngram(text.split(),2)

 
実行結果
haruka@ubuntu:~/NLP100$ python 05.py
['I ', ' a', 'am', 'm ', ' a', 'an', 'n ', ' N', 'NL', 'LP', 'Pe', 'er']
[['I', 'am'], ['am', 'an'], ['an', 'NLPer']]

06.集合

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

06.py
#coding: UTF-8
txt1 = "paraparaparadise"
txt2 = "paragraph"

def ngram(text,n):
  list = []
  if len(text) >= n:
      for i in xrange(len(text) - n + 1):
          list.append(text[i:i+n])
  return list

X = set(ngram(txt1,2))
Y = set(ngram(txt2,2))

print X,Y

print ("wa:%s" % list(X|Y))
print ("seki:%s" % list(X&Y))
print ("sa:%s" % list(X-Y))

print u"\"se\"はXに含まれているか:"
print "se" in list(X)

print u"\"se\"はYに含まれているか:"
print "se" in list(Y)

実行結果
haruka@ubuntu:~/NLP100$ python 06.py
set(['ad', 'di', 'is', 'ap', 'pa', 'ra', 'ar', 'se']) set(['gr', 'ag', 'ap', 'pa', 'ra', 'ph', 'ar'])
wa:['ad', 'ag', 'di', 'is', 'ap', 'pa', 'ra', 'ph', 'ar', 'se', 'gr']
seki:['ap', 'pa', 'ar', 'ra']
sa:['is', 'ad', 'se', 'di']
"se"はXに含まれているか:
True
"se"はYに含まれているか:
False

09. Typoglycemia

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

09.py
#coding: UTF-8
import random

text = "I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."

list = []

def typo(text):
  for i in text.split():
    if len(i) > 4:
      naka = random.sample(list(i[1:-1]))
      #i = "".join(naka)
      list.append(i[0:1] + naka + i[-1])
    elif len(text) <= 4:
      list.append(i)
  return "".join(list)

print typo(text)

実行結果
haruka@ubuntu:~/NLP100$ python 09.py
Traceback (most recent call last):
File "09.py", line 18, in
print typo(text)
File "09.py", line 11, in typo
naka = random.sample(list(i[1:-1]))
TypeError: 'list' object is not callable

第2章: UNIXコマンドの基礎

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

11.タブをスペースに置換

タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.

11.py
#coding: UTF-8

with open("hightemp.txt","r") as f:
  print (f.read()).replace("\t"," ")

実行結果
haruka@ubuntu:~/NLP100$ python 11.py
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02

コマンド確認
haruka@ubuntu:~/NLP100$ sed 's/\t/ /g' hightemp.txt
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02

12.1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

12.py
#coding: UTF-8

with open("hightemp.txt","r") as f:
    col1 = open("col1.txt","w")
    col2 = open("col2.txt","w")
    for line in f:
        col1.write(line.split()[0] + "\n")
        col2.write(line.split()[1] + "\n")
    col1.close()
    col2.close()

実行結果

col1.txt
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県
col2.txt
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋

コマンド確認
haruka@ubuntu:~/NLP100$ cut -f1 hightemp.txt > c_col1.txt
haruka@ubuntu:~/NLP100$ cut -f2 hightemp.txt > c_col2.txt

c_col1.txt
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県
c_col2.txt
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋

13.col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

13.py
#coding: UTF-8

col1 = open("col1.txt")
col2 = open("col2.txt")

with open("merge_col1_col2.txt","w") as f:
  for i,j in zip(col1,col2):
    f.write(i.strip() + "\t" + j.strip() + "\n")

col1.close
col2.close

実行結果

merge_col1_col2.txt.txt
高知県   江川崎
埼玉県   熊谷
岐阜県   多治見
山形県   山形
山梨県   甲府
和歌山県    かつらぎ
静岡県   天竜
山梨県   勝沼
埼玉県   越谷
群馬県   館林
群馬県   上里見
愛知県   愛西
千葉県   牛久
静岡県   佐久間
愛媛県   宇和島
山形県   酒田
岐阜県   美濃
群馬県   前橋
千葉県   茂原
埼玉県   鳩山
大阪府   豊中
山梨県   大月
山形県   鶴岡
愛知県   名古屋

コマンド確認
haruka@ubuntu:~/NLP100$ paste c_col1.txt c_col2.txt > c_merge_col1_col2.txt

c_merge_col1_col2.txt
高知県   江川崎
埼玉県   熊谷
岐阜県   多治見
山形県   山形
山梨県   甲府
和歌山県    かつらぎ
静岡県   天竜
山梨県   勝沼
埼玉県   越谷
群馬県   館林
群馬県   上里見
愛知県   愛西
千葉県   牛久
静岡県   佐久間
愛媛県   宇和島
山形県   酒田
岐阜県   美濃
群馬県   前橋
千葉県   茂原
埼玉県   鳩山
大阪府   豊中
山梨県   大月
山形県   鶴岡
愛知県   名古屋

14.先頭からN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.

14.py
#coding: UTF-8
import sys

argvs = sys.argv[1]

with open("hightemp.txt","r") as f:
  lines = f.readlines()
  for i in xrange(int(argvs)):
      print lines[i],

実行結果
haruka@ubuntu:~/NLP100$ python 14.py 5
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10

コマンド確認
haruka@ubuntu:~/NLP100$ head -5 "hightemp.txt"
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10

15.末尾のN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.

15.py
#coding: UTF-8
import sys

argvs = sys.argv[1]

with open("hightemp.txt","r") as f:
  lines = f.readlines()[::-1]
  #lines = lines.reverse() 
  for i in xrange(int(argvs)):
      print lines[i],

実行結果
haruka@ubuntu:~/NLP100$ python 15.py 5
愛知県 名古屋 39.9 1942-08-02
山形県 鶴岡 39.9 1978-08-03
山梨県 大月 39.9 1990-07-19
大阪府 豊中 39.9 1994-08-08
埼玉県 鳩山 39.9 1997-07-05

コマンド確認
haruka@ubuntu:~/NLP100$ tail -5 "hightemp.txt"
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02

17.1列目の文字列の異なり

1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.

17.py
#coding: UTF-8

k = set("")
with open("hightemp.txt","r") as f:
  for line in f:
    ki = k.add((line.split()[0])
  for i in ki
    print i

実行結果
haruka@ubuntu:~/NLP100$ python 17.py
set(['\xa5', '\xe7', '\xe9', '\xab', '\x8c', '\x98', '\x9c', '\x9f']) set(['\x9c', '\xe5', '\xe7', '\x89', '\x8c', '\x8e', '\xbc', '\x9f']) set(['\xe5', '\xe7', '\xe9', '\x8c', '\x90', '\xb2', '\x98', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\x8c', '\xb1', '\xbd', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\xe6', '\xa8', '\x8c', '\xb1', '\x9c']) set(['\xe5', '\xe7', '\xe6', '\xad', '\x8c', '\xb1', '\x92', '\x9c']) set(['\xa1', '\xe5', '\xe7', '\xe9', '\x8c', '\xb2', '\x99', '\x9d', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\xe6', '\xa8', '\x8c', '\xb1', '\x9c']) set(['\x9c', '\xe5', '\xe7', '\x89', '\x8c', '\x8e', '\xbc', '\x9f']) set(['\xa4', '\xe7', '\xa6', '\xe9', '\xac', '\x8c', '\x9c', '\xbe']) set(['\xa4', '\xe7', '\xa6', '\xe9', '\xac', '\x8c', '\x9c', '\xbe']) set(['\xa5', '\x84', '\xe7', '\xe6', '\x8c', '\x9b', '\x9c', '\x9f']) set(['\x83', '\xe5', '\xe7', '\x89', '\xe8', '\x8d', '\x8c', '\x91', '\x9c']) set(['\xa1', '\xe5', '\xe7', '\xe9', '\x8c', '\xb2', '\x99', '\x9d', '\x9c']) set(['\xe5', '\x84', '\xe7', '\xe6', '\xaa', '\x8c', '\x9b', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\x8c', '\xb1', '\xbd', '\x9c']) set(['\xe5', '\xe7', '\xe9', '\x8c', '\x90', '\xb2', '\x98', '\x9c']) set(['\xa4', '\xe7', '\xa6', '\xe9', '\xac', '\x8c', '\x9c', '\xbe']) set(['\x83', '\xe5', '\xe7', '\x89', '\xe8', '\x8d', '\x8c', '\x91', '\x9c']) set(['\x9c', '\xe5', '\xe7', '\x89', '\x8c', '\x8e', '\xbc', '\x9f']) set(['\xe5', '\xa4', '\xa7', '\xe9', '\xaa', '\x98', '\xba', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\xe6', '\xa8', '\x8c', '\xb1', '\x9c']) set(['\xa2', '\xe5', '\xe7', '\x8c', '\xb1', '\xbd', '\x9c']) set(['\xa5', '\x84', '\xe7', '\xe6', '\x8c', '\x9b', '\x9c', '\x9f'])

コマンド確認
haruka@ubuntu:~/NLP100$ cut -f1 "hightemp.txt" | sort | uniq
愛知県
愛媛県
岐阜県
群馬県
高知県
埼玉県
山形県
山梨県
静岡県
千葉県
大阪府
和歌山県

第3章:正規表現

Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.

1行に1記事の情報がJSON形式で格納される
各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
ファイル全体はgzipで圧縮される
以下の処理を行うプログラムを作成せよ.

20.JSONデータの読み込み

Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.

20.py
#coding: UTF-8

import json
from io import StringIO
import re

with open("jawiki-country.json","rt") as f:
  for line in f:
    jsondata = json.load(StringIO(line))
    if data["title"] == u"イギリス":
      england = jsondata["england.txt"]

print england

実行結果
haruka@ubuntu:~/NLP100$ python 20.py
Traceback (most recent call last):
File "20.py", line 9, in
jsondata = json.load(StringIO(line))
TypeError: initial_value must be unicode or None, not str

第4章:形態素解析

夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ.

なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

Mecabのインストールをする。
haruka@ubuntu:~/NLP100$ pip install mecab
neko.txtをMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存する。
haruka@ubuntu:~/NLP100$ mecab neko.txt -o neko.txt.mecab
neko.txt.mecabを貼り付けたらQiitaがかたまってたしまうので貼らない。

30.形態素解析結果の読み込み

形態素解析結果(neko.txt.mecab)を読み込むプログラムを実装せよ.ただし,各形態素は表層形(surface),基本形(base),品詞(pos),品詞細分類1(pos1)をキーとするマッピング型に格納し,1文を形態素(マッピング型)のリストとして表現せよ.第4章の残りの問題では,ここで作ったプログラムを活用せよ.

Mecabの公式サイトによると出力フォーマットは
表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音
このようになっているらしい。
でも出力フォーマットは変更できるので今回のデータのフォーマットだと違うかも知れない→neko.txt.mecabから何行かひっぱってきた
吾輩 名詞,代名詞,一般,,,,吾輩,ワガハイ,ワガハイ,,
→表層形\t品詞,?,?,?,?,?,原形,読み,読み,?,
無い 形容詞,自立,
,,形容詞・アウオ段,基本形,無い,ナイ,ナイ,ない/無い,
→表層形\t品詞,?,?,?,活用型,活用形,原形,読み,発音,複数候補,
生れ 動詞,自立,
,*,一段,連用形,生れる,ウマレ,ウマレ,うまれ/生まれ/生れ,
→表層形\t品詞,?,?,?,活用型,活用形,原形,読み,発音,複数候補,

どうやら今回のデータ(neko.txt.mecab)のフォーマットは
表層形\t品詞,おそらく品詞細分類1,おそらく品詞細分類2,おそらく品詞細分類3,活用型,活用形,原形,読み,発音,複数候補,
らしい。

表層形(surface)とは単語そのもののこと。フォーマットの1カラム目に該当する。
基本形(base)は活用形の1種?。
品詞(pos)とは単語を動詞・形容詞・形容動詞・名詞・代名詞・副詞・連体詞・接続詞・感動詞・助詞・助動詞の11グループに分けたもの。品詞の定義は様々だと思うけどMecabの品詞の定義はどうなってるんだろう。フォーマットの2カラム目に該当する。
品詞細分類1(pos1)は品詞を更に細かく分類したもの。フォーマットの3カラム目に該当する。

今日のまとめ
さっぱりいまは解ける気がしないけどなんとかなるのかな。
検索に関わりたい。
今日解けたのは02,04,05,06,11,12,13,14

1問解けたら絵をかいたふせんをはってくってのをやって気づいたことはふせんは剥がれやすい 
今日のしんちょく
CiLRVw5UoAAwZV-.jpg

言語処理100本ノック 2015のリンク
言語処理100本ノック 2015 1日目
言語処理100本ノック 2015 2日目
言語処理100本ノック 2015 3日目
言語処理100本ノック 2015 4日目
言語処理100本ノック 2015 5日目
言語処理100本ノック 2015 6日目