読者です 読者をやめる 読者になる 読者になる

or1ko's diary

日々を書きます

17

言語処理100本ノック 2015

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

> Get-Content -Encoding utf8 .\hightemp.txt | ConvertFrom-Csv -Header a -Delimiter `t |
 % { $_.a } | Sort-Object -Unique
愛知県
愛媛県
岐阜県
群馬県
高知県
埼玉県
山形県
山梨県
静岡県
千葉県
大阪府
和歌山県

17.hs

import System.Environment
import System.IO.UTF8 as I8
import Data.List 

main = do
  filename <- getArgs >>= return . head
  body <- I8.readFile filename
  I8.writeFile "17.out.txt" $ unlines $ nub . sort . map (head . words) $ lines body

shのsortを動かくのが面倒だったため、PowerShellで実施することにした。

16

言語処理100本ノック 2015

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

16.hs

import System.Environment
import Control.Monad

main = do
  args <- getArgs
  let num = (read :: String -> Int) $ head args
  let filename = args !! 1
  body <- getContents 
  let l = lines body
  let a = div (length l) num + mod (length l) num
  let b = splitAt' a l
  mapM_ (\x -> writeFile (filename ++ (show x) ++ ".txt") $ unlines (b !! (x - 1))) [1..num] 

splitAt' n xs 
  | length xs <= n = [xs]
  | otherwise = x :(splitAt' n y) 
    where
      (x, y) = splitAt n xs

結構、プログラムが長くて、読みにくくなってしまった。行をn個に分割する関数を定義したら、良かったかもしれない。

15

言語処理100本ノック 2015

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

> tail -n 10

15.hs

import System.Environment

main = do
  num <- getArgs >>= return . (read :: String -> Int) . head 
  body <- getContents 
  putStrLn $ unlines $ reverse $ take num $ reverse $ lines body

14.hsを流用したが、
このプログラムだと、入力された文字列を瞬間的に全部保持する!?

14

言語処理100本ノック 2015

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

>head -n 10 

14.hs

import System.Environment

main = do
  num <- getArgs >>= return . (read :: String -> Int) . head 
  body <- getContents 
  putStrLn $ unlines $ take num $ lines body

13

言語処理100本ノック 2015

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

pasteコマンドなかったため未実施。たぶん下記の通り。

>paste col1.txt col2.txt

13.hs

import System.Environment
import System.IO.UTF8 as I8
import Data.List

main = do
  files <- getArgs
  body <- mapM (\x -> I8.readFile x >>= return . lines) files
  I8.writeFile "out.txt" $ unlines $ map unwords $ transpose body

実行は省略。文字列の出力処理に悩む。

12

言語処理100本ノック 2015

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

> cut -f 1 hightemp.txt > col1.txt
> cut -f 2 hightemp.txt > col2.txt

12.hs

import System.IO as I
import System.Environment
import System.IO.UTF8 as I8

main = do
  file <- getArgs >>= return . head
  body <- I8.readFile file
  let wss = map words $ lines body
  I.writeFile "col1.txt" $ unlines $ map head wss
  I.writeFile "col2.txt" $ unlines $ map (last . take 2) wss

実行結果は省略。

11

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

>sed "s/\t/ /g" hightemp.txt
>tr "\t" " " < hightemp.txt

expandはなかったためやめる。

11.hs

import System.IO.UTF8 as I8
import System.Environment
import Prelude as P

main = do
  filename <- getArgs >>= return . head
  body <- I8.readFile filename
  P.putStrLn $ unlines $ map (map f) $ lines body
    where
      f '\t' = ' '
      f x = x

読み込みはutf8-stringで、出力がPreludeという組み合わせで
うまくいくのがよくわからないが、ひとまずこれで。