LoginSignup
3
0

More than 5 years have passed since last update.

素人の言語処理100本ノック:16

Last updated at Posted at 2016-10-01

言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。

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

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

16.ファイルをN分割する

自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.

出来上がったコード:

main.py
# coding: utf-8
import math

fname = 'hightemp.txt'
n = int(input('N--> '))

with open(fname) as data_file:
    lines = data_file.readlines()

count = len(lines)
unit = math.ceil(count / n)  # 1ファイル当たりの行数

for i, offset in enumerate(range(0, count, unit), 1):
    with open('child_{:02d}.txt'.format(i), mode='w') as out_file:
        for line in lines[offset:offset + unit]:
            out_file.write(line)

実行結果:

一例として、N=5の場合の結果を載せます。
全部で24行なので、5分割すると各ファイルは5行になり、最後のファイルだけは4行になります。

child_01.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
child_02.txt
和歌山県    かつらぎ    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
child_03.txt
群馬県   上里見   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
child_04.txt
山形県   酒田  40.1    1978-08-03
岐阜県   美濃  40  2007-08-16
群馬県   前橋  40  2001-07-24
千葉県   茂原  39.9    2013-08-11
埼玉県   鳩山  39.9    1997-07-05
child_05.txt
大阪府   豊中  39.9    1994-08-08
山梨県   大月  39.9    1990-07-19
山形県   鶴岡  39.9    1978-08-03
愛知県   名古屋   39.9    1942-08-02

UNIXコマンド確認用のシェルスクリプト:

test.sh
#!/bin/sh

# Nを入力
echo -n "N--> "
read n

# 行数算出 wcは行数とファイル名を出力するのでcutで行数のみ切り出し
count=`wc --line hightemp.txt | cut --fields=1 --delimiter=" "`

# 1分割当たりの行数算出 余りがある場合は行数を+1
unit=`expr $count / $n`
remainder=`expr $count % $n`
if [ $remainder -gt 0 ]; then
    unit=`expr $unit + 1`
fi

# 分割
split --lines=$unit --numeric-suffixes=1 --additional-suffix=.txt hightemp.txt child_test_

# 検証
for i in `seq 1 $n`
do
    fname=`printf child_%02d.txt $i`
    fname_test=`printf child_test_%02d.txt $i`
    diff --report-identical-files $fname $fname_test
done

結果の確認:

いくつかの結果を載せます。

N=1の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py 
N--> 1
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 1
ファイル child_01.txt と child_test_01.txt は同一です

N=2の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py 
N--> 2
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 2
ファイル child_01.txt と child_test_01.txt は同一です
ファイル child_02.txt と child_test_02.txt は同一です

N=5の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py 
N--> 5
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 5
ファイル child_01.txt と child_test_01.txt は同一です
ファイル child_02.txt と child_test_02.txt は同一です
ファイル child_03.txt と child_test_03.txt は同一です
ファイル child_04.txt と child_test_04.txt は同一です
ファイル child_05.txt と child_test_05.txt は同一です

N=7の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py 
N--> 7
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 7
ファイル child_01.txt と child_test_01.txt は同一です
ファイル child_02.txt と child_test_02.txt は同一です
ファイル child_03.txt と child_test_03.txt は同一です
ファイル child_04.txt と child_test_04.txt は同一です
ファイル child_05.txt と child_test_05.txt は同一です
ファイル child_06.txt と child_test_06.txt は同一です
diff: child_07.txt: そのようなファイルやディレクトリはありません
diff: child_test_07.txt: そのようなファイルやディレクトリはありません

今回のプログラムでは6分割しかされないので、7分割目のファイルがない旨のエラーになります。これは、全24行を7分割しようとすると1ファイル当たり4行になってしまい、6ファイルで済んでしまうロジックのためです。
もしかしたら、4行のファイルを3つと、3行のファイルを4つに分割しないといけないかも知れません。このコードだと不正解かも...^^;

N=24の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py
N--> 24
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 24
ファイル child_01.txt と child_test_01.txt は同一です
ファイル child_02.txt と child_test_02.txt は同一です
ファイル child_03.txt と child_test_03.txt は同一です
ファイル child_04.txt と child_test_04.txt は同一です
ファイル child_05.txt と child_test_05.txt は同一です
ファイル child_06.txt と child_test_06.txt は同一です
ファイル child_07.txt と child_test_07.txt は同一です
ファイル child_08.txt と child_test_08.txt は同一です
ファイル child_09.txt と child_test_09.txt は同一です
ファイル child_10.txt と child_test_10.txt は同一です
ファイル child_11.txt と child_test_11.txt は同一です
ファイル child_12.txt と child_test_12.txt は同一です
ファイル child_13.txt と child_test_13.txt は同一です
ファイル child_14.txt と child_test_14.txt は同一です
ファイル child_15.txt と child_test_15.txt は同一です
ファイル child_16.txt と child_test_16.txt は同一です
ファイル child_17.txt と child_test_17.txt は同一です
ファイル child_18.txt と child_test_18.txt は同一です
ファイル child_19.txt と child_test_19.txt は同一です
ファイル child_20.txt と child_test_20.txt は同一です
ファイル child_21.txt と child_test_21.txt は同一です
ファイル child_22.txt と child_test_22.txt は同一です
ファイル child_23.txt と child_test_23.txt は同一です
ファイル child_24.txt と child_test_24.txt は同一です

N=25の場合:

端末
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ python main.py
N--> 25
segavvy@ubuntu:~/ドキュメント/言語処理100本ノック2015/16$ ./test.sh
N--> 25
ファイル child_01.txt と child_test_01.txt は同一です
ファイル child_02.txt と child_test_02.txt は同一です
ファイル child_03.txt と child_test_03.txt は同一です
ファイル child_04.txt と child_test_04.txt は同一です
ファイル child_05.txt と child_test_05.txt は同一です
ファイル child_06.txt と child_test_06.txt は同一です
ファイル child_07.txt と child_test_07.txt は同一です
ファイル child_08.txt と child_test_08.txt は同一です
ファイル child_09.txt と child_test_09.txt は同一です
ファイル child_10.txt と child_test_10.txt は同一です
ファイル child_11.txt と child_test_11.txt は同一です
ファイル child_12.txt と child_test_12.txt は同一です
ファイル child_13.txt と child_test_13.txt は同一です
ファイル child_14.txt と child_test_14.txt は同一です
ファイル child_15.txt と child_test_15.txt は同一です
ファイル child_16.txt と child_test_16.txt は同一です
ファイル child_17.txt と child_test_17.txt は同一です
ファイル child_18.txt と child_test_18.txt は同一です
ファイル child_19.txt と child_test_19.txt は同一です
ファイル child_20.txt と child_test_20.txt は同一です
ファイル child_21.txt と child_test_21.txt は同一です
ファイル child_22.txt と child_test_22.txt は同一です
ファイル child_23.txt と child_test_23.txt は同一です
ファイル child_24.txt と child_test_24.txt は同一です
diff: child_25.txt: そのようなファイルやディレクトリはありません
diff: child_test_25.txt: そのようなファイルやディレクトリはありません

全部で24行しかないので、25分割はできません。このエラーは仕方ないかと思います。

今回はpythonよりもシェルスクリプトに苦労しましたが、少し慣れてきました。printfというコマンドまであることを知って、UNIXコマンドの多彩さに驚いています。
 
17本目のノックは以上です(いつも最後に書いているノックの本数が1本ずれていませんか?とのご指摘をいただきましたが、このノックの最初の問題番号は0なので、問題番号とは1本ずれています)。誤りなどありましたら、ご指摘いただけますと幸いです。

3
0
2

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
3
0