プログラミングHaskell (第五章の練習問題)

in

5.7 (1) リスト内包表記を使って1から100の二乗の和を計算する式を考えよ

sum' = sum[x^2 | x <- [1..100]]

まぁまぁ、このあたりは...ね。

5.7 (2) replicateをリスト内包表記を使って定義せよ

replicate':: Int -> a -> [a]
replicate' n a | n > 0     = [ a | _ <- [0..n-1] ]
               | otherwise = []

個数に0を与えられた場合どうすべきか迷いましたが、空リストを返します。3.5章に"全域関数"(僕はこの言葉知りませんでした)について触れられていますが、ghcで色々試していると予想以上に部分関数が多い気がします。本問題でもn=0には触れられていないので未定義でも良いのかもしれません。また、この問題をやるときに何故かrepeatを知っていたので

replicate' n a = take n [a'|a' <- repeat a]

を最初に考えましたが、これじゃ練習にならないと思い直し、上記の解答としました。

5.7 (3) 与えられた上限以下のピタゴラス数を生成する関数をリスト内包表記を使って定義せよ

pyths:: Int -> [(Int,Int,Int)]
pyths n = [(p1,p2,p3) | (p1,p2,p3) <- all , p1^2 + p2^2 == p3^2]
       where all = [(a1,a2,a3) | a1 <- [1..n], a2 <- [1..n], a3 <- [1..n]]

この手のループが入れ子になる問題は苦手。allの定義は頭の中だけでは完成できませんでした。実際、コードを書いてみなけりゃ..

5.7 (4) 与えられた上限までに含まれる完全数を算出する関数をリスト内包表記と関数factorsを使って定義せよ

perfects:: Int -> [Int]
perfects n = [ p | p <- [2..n],sum(tail(reverse (factors p))) == p]
           where factors p = [ x | x <- [1..p], p `mod` x == 0 ]

素数を求めるfactorsは本文中にあるものそのまま。できあがったリストの末尾が自分自身なので、"自分自身を除く約数の和"はひっくり返してtailしたリストの和で取得しました。

5.7 (5) 二つの生成器を持つリスト内包表記を一つの生成器を持つリスト内包表記二つで表現せよ

a  = [(x,y)| x <- [1,2,3], y <- [4,5,6]]
a' = concat [x|x<-[(y' 1),(y' 2),(y' 3)]]
    where y' n = [(n,y)|y<-[4,5,6]]

これは難しかった。しかもやや反則気味ですが、一応"一つの生成器を持つリスト内包表記を二つ"になっています。が、解答は

concat [[(x,y) | y <- [4,5,6]] | x <- [1,2,3]]

これは全然思いつかなかったから不正解です。まぁ、”こういう書き方ができる"ってことを知っているか知らないかだけの問題なのでショックはありませんが、最初にこのこの解答をみたとき、"二つの生成器を持つ一つのリスト内包表記"のように読んでしまったところがまだ慣れていないと言うことでしょう。よく見ると、最初の生成器の後ろで最初の内包表記は閉じていますね。

5.7 (6) 関数positionsを関数findを使って再定義せよ

positions'::Eq a => a -> [a] -> [Int]
positions' x xs = find x (tbl xs)
            where tbl xs = zip xs [0..(length xs -1)]
                  find k t = [v|(k',v)<-t,k==k']

これはいいでしょ。解答では、whereに"length xs -1"の部分をもってきて

positions x xs = find x (zip xs [0..n])
               where n = length xs − 1

のようになっています。

5.7 (7) scalarproduct::[Int]->[Int]->Intをリスト内包表記を使って定義出来ることを示せ

scalarproduct::[Int] -> [Int] -> Int
scalarproduct xs ys = sum[x' * y'|(x',y') <- zip xs ys]

問題文にはおどろおどろしい数式がでていますが、書いてみればどうってことないかな?

5.7 (8) シーザー暗号のプログラムを大文字も扱えるように変更せよ

長くなったのでこれは次回のエントリで投稿します。(ちゃんとやりますよ)

添付サイズ
ex5.hs1.25 KB

この記事のトラックバックURL:

http://hippos-lab.com/blog/trackback/351

Comments