はじめに
言語処理100本ノック 2015という素敵教材をド素人が挑戦していく記事です。
道のり
〜言語処理100本ノック No.00-04〜
〜言語処理100本ノック No.05-09〜
〜言語処理100本ノック No.10-14〜
環境
Mac OS X 10.14.5
Python 3.7.1
準備
- 「hightemp.txt」というテキストがサイトに用意してあるので、ローカルに配置します。
15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
Pythonで実行
# python 15.py hightemp.txt 3
import sys
# ファイルの読み込み
f = open(sys.argv[1], 'r').readlines()
# 末尾何行を出力するのかの引数格納
line_num = 0
line_num = int(sys.argv[2])
# 末尾N行出力
for line in (f[len(f) - line_num:len(f)]):
print(line,end="")
確認(Linuxコマンド)
$ tail -n 3 hightemp.txt
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.
Pythonで実行
# python 16.py hightemp.txt 7
import sys
# ファイルの読み込み
f = open(sys.argv[1], 'r').readlines()
# ファイルの行数の確認
text_linesize = len(f)
# 何行ずつに区切るのか引数の格納
line_num = 0
line_num = int(sys.argv[2])
file_num = 1
# 末尾N行出力
for i in range(0,len(f),line_num):
file_name = 'output/chap_2_16_python_'+str(file_num)
fnew = open (file_name, 'w')
for x in f[i:i+line_num]:
fnew.write(str(x))
fnew.close()
file_num += 1
# ls output/chap_2_16_python_*
# output/chap_2_16_python_1 output/chap_2_16_python_2 output/chap_2_16_python_3 output/chap_2_16_python_4
確認(Linuxコマンド)
# -l で何行ずつ区切るか
# ファイル名のあとに指定した名前でファイルが作成される(末尾にa,bとついていく)。
# ファイル名は変更できる
$ split -l 7 hightemp.txt chap_2_16_linux_
$ ls -l chap_2_16_linux_a*
-rw-r--r-- 1 itnewcomer staff 244 6 27 23:20 chap_2_16_linux_aa
-rw-r--r-- 1 itnewcomer staff 237 6 27 23:20 chap_2_16_linux_ab
-rw-r--r-- 1 itnewcomer staff 230 6 27 23:20 chap_2_16_linux_ac
-rw-r--r-- 1 itnewcomer staff 102 6 27 23:20 chap_2_16_linux_ad
$ cat chap_2_16_linux_aa
高知県 江川崎 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
$ cat chap_2_16_linux_ad
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.
Pythonで実行
# python 17.py hightemp.txt
import sys
print("17. 1列目の文字列の異なり")
# ファイルの読み込み
f = open(sys.argv[1], 'r').readlines()
# リストの初期化
word_list = list()
# 1列目のみをリスト化
for line in f:
word_list.append(line.split()[0])
# 集合にする
word_list = set(word_list)
# 表示
print(word_list)
確認(Linuxコマンド)
# -f 何列目か
# -d 区切り文字の指定
$ cut -f 1 -d "$(printf "\t")" hightemp.txt | sort |uniq
千葉県
埼玉県
大阪府
山形県
山梨県
岐阜県
愛媛県
愛知県
群馬県
静岡県
高知県
和歌山県
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).
確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
Pythonで実行
# python 18.py hightemp.txt
import sys
from operator import itemgetter
# ファイルの読み込み
f = open(sys.argv[1], 'r').readlines()
# 多次元配列の作成
my_list = list()
for line in f:
my_list.append(line.split())
# operatorモジュールを使用
# keyにソートしたい要素を指定
print(sorted(my_list, key=itemgetter(2),reverse=True))
# [
# ['高知県', '江川崎', '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']
# ]
確認(Linuxコマンド)
# -k keyとなる列
# -t 区切り文字
# -r reverse
$ sort -k 3 -t "$(printf "\t")" -r hightemp.tx
高知県 江川崎 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
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
Pythonで実行
# python 19.py hightemp.txt
import collections
import sys
# ファイルの読み込み
f = open(sys.argv[1], 'r').readlines()
# リストの初期化
word_list = list()
# 1列目のみをリスト化
for line in f:
word_list.append(line.split()[0])
# Python標準ライブラリcollectionsにCounterクラスを利用
c = collections.Counter(word_list)
print(c)
# Counter({'埼玉県': 3, '山形県': 3, '山梨県': 3, '群馬県': 3, '岐阜県': 2, '静岡県': 2, '愛知県': 2, '千葉県': 2, '高知県': 1, '和歌山県': 1, '愛媛県': 1, '大阪府': 1})
確認(Linuxコマンド)
# -f 切り出す列番指定
# -d 区切り文字の指定
# uniq -c で各要素が何個あるか出せる
# sort -n 数値として並び替える
# sort -r 降順
$ cut -f 1 -d "$(printf "\t")" hightemp.txt | sort |uniq -c |sort -nr
3 群馬県
3 山梨県
3 山形県
3 埼玉県
2 静岡県
2 愛知県
2 岐阜県
2 千葉県
1 和歌山県
1 高知県
1 愛媛県
1 大阪府
最後に
今回は結構時間かかりました。
Linuxは普段文字列操作系はあまり使わないので、色々調べて楽しかったのです。
なにかお気づきの点あればコメントいただけると幸いです。