「ANSI Common Lisp」3章練習問題 - Haskell版
2. もとのリストでの要素の並びを保持するように動作するunionの変形版を書け。
newUnion::(Eq a) => [a] -> [a] -> [a] newUnion x [] = x newUnion x (y:ys) = if elem y x then newUnion x ys else newUnion (x ++ [y]) ys main = print $ newUnion "abc" "bad"
結果はこう。
"abcd"
3. 1つのリストを引数として、おのおのの要素について同じもの(eqlで比較)が出現する回数を示すリストを返す関数を定義せよ。ただし、結果は回数が多い順に並べ替えて返すものとする。
import List import Maybe occurrences::(Eq a, Num b) => [a] -> [(a, b)] occurrences [] = [] occurrences (x:xs) = let resultList = occurrences xs ifInclude = (lookup x resultList) in if ifInclude == Nothing then ((x,1) : resultList) else (x, (fromJust ifInclude) + 1) : (deleteTupleList x resu ltList) -- タプルのリストから指定要素のタプルを取り除く -- (指定要素以外のタプルを集める) deleteTupleList::(Eq a) => a -> [(a,b)] -> [(a,b)] deleteTupleList a b = [ x | x <- b, (fst x) /= a ] main = print $ sortBy (\a b-> compare (snd b) (snd a)) $ occurrences "abadacdca"
結果はこう。
[('a',4),('d',2),('c',2),('b',1)]
5. 関数pos+は1つのリストを引数として、おのおのの要素にその位置を示す数を加えて返す。この関数を、(a)再帰を用いる、(b)反復を用いる、(c)mapcarを用いる、の3通りで定義せよ。
-- (a) 再帰版 posPlusRecursive::[Int] -> [Int] posPlusRecursive [] = [] posPlusRecursive xs = (posPlusRecursive (take ((length xs) - 1) xs)) ++ [((last xs) + (length xs) - 1)] -- (b) 反復版 ==> (c)と同じ? -- (c) mapcar版 posPlusMapcar::(Num a, Enum a) => [a] -> [a] posPlusMapcar xs = map (\n -> (fst n) + (snd n)) $ zip xs [0..] -- mainルーチン(テストドライバ) main = do print $ posPlusMapcar [7,5,1,4] print $ posPlusRecursive [7,5,1,4]
haskellでは反復って無かったと思うので、map版と同じとみなしました。
結果はこう。
[7,6,3,7] [7,6,3,7]
8. 1つのリストを引数としてドット表記で表示する関数を定義せよ。
printListByDottedFormat::(Show a) => [a] -> String printListByDottedFormat [] = "NIL" printListByDottedFormat (x:xs) = "(" ++ (show x) ++ " . " ++ (printListByDottedFormat xs) ++ ")" main = do print $ printListByDottedFormat "abc" print $ printListByDottedFormat [1..3]
結果はこう。
"('a' . ('b' . ('c' . NIL)))" "(1 . (2 . (3 . NIL)))"