Help us understand the problem. What is going on with this article?

僕はプログラミングができません④ 〜言語処理100本ノック No.15-19〜

はじめに

言語処理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で実行

15.py
# 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で実行

16.py
# 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で実行

17.py
# 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で実行

18.py
# 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で実行

19.py
# 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は普段文字列操作系はあまり使わないので、色々調べて楽しかったのです。
なにかお気づきの点あればコメントいただけると幸いです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away