19
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
19.hs
import System.Environment import System.IO.UTF8 as I8 import qualified Data.Map as M import Data.List import Data.Maybe main = do filename <- getArgs >>= return . head body <- I8.readFile filename let cfs = M.fromList $ map (\x -> (head x, length x) ) $ group $ sort $ map (head . words) $ lines body I8.writeFile "19.out.txt" $ unlines $ sortBy (\x y -> compareByCf cfs (head $ words x) (head $ words y)) $ lines body compareByCf cfs x y = fromMaybe EQ $ do xt <- M.lookup x cfs yt <- M.lookup y cfs return $ compare xt yt
実行結果が出現頻度順に並んでないと勘違いして、だいぶ悩んでしまった。
出現頻度順に並んでも、同じ単語が続けて現れるわけではないですね...。
18
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
> Get-Content -Encoding UTF8 .\hightemp.txt | ConvertFrom-Csv -Header a,b,c,d -Delimite r `t | Sort-Object -Property c
18.hs
import System.Environment import System.IO.UTF8 as I8 import Data.List import Data.Ord main = do filename <- getArgs >>= return . head body <- I8.readFile filename I8.writeFile "18.out.txt" $ unlines $ nub . sortBy (\x y -> compare (f y) (f x)) $ lines body where f = flip (!!) 2 . words
17
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
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
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を流用したが、
このプログラムだと、入力された文字列を瞬間的に全部保持する!?
13
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
実行は省略。文字列の出力処理に悩む。