プログラマとプロマネのあいだ

プログラマもやるし、プロマネもやるし、たまに似非アーキとか営業っぽいこともやる

「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)))"