Ninety-Nine Haskell Problems 8

1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all
Ninety-Nine Haskell Problems


八問目.

8 Problem 8

(**) Eliminate consecutive duplicates of list elements.

If a list contains repeated elements they should be replaced with a single copy of the element. 
The order of the elements should not be changed.

Example:
* (compress '(a a a a b c c a a d e e e e))
(A B C A D E)

Example in Haskell:
*Main> compress ['a','a','a','a','b','c','c','a','a','d','e','e','e','e']
['a','b','c','a','d','e']
http://www.haskell.org/haskellwiki/99_questions/1_to_10#Problem_8

で,とりあえず,Haskell/Control structuresで,if文について調べて,できたのが次.

compress (x:(y:[])) = if x == y then [x] else [x, y]
compress (x:(y:ys)) = if x == y then compress (y:ys) else ([x] ++ compress (y:ys))

これで実行してみると,

Main> compress [1,1, 2]
[1,2]
Main> compress [1,2]
[1,2]
Main> compress [1,1,1,2,2,3,4,4,4,5,1,1,2]
[1,2,3,4,5,1,2]

おお,なんかうまくいってる模様.
しかし,

Main> compress ['a','a','a','a','b','c','c','a','a','d','e','e','e','e']
"abcade"

駄目でした.
うーん,一回切り離してから,文字を結合してるから,全部繋がって文字列になっちゃうってわけだな.
と,思ったけど,

Main> ['a','b','c','a','d','e']
"abcade"

ってなるから,いいのかな?どういうこっちゃ.
とりあえず,解答.

Solution:

compress :: Eq a => [a] -> [a]
compress = map head . group

We simply group equal values together (group), then take the head of each. Note that (with GHC) 
we must give an explicit type to compress otherwise we get:

Ambiguous type variable `a' in the constraint:
      `Eq a'
	arising from use of `group'	
    Possible cause: the monomorphism restriction applied to the following:
      compress :: [a] -> [a]
    Probable fix: give these definition(s) an explicit type signature
		  or use -fno-monomorphism-restriction

We can circumvent the monomorphism restriction by writing compress this way 
(See: section 4.5.4 of the report):

compress xs = map head $ group xs

An alternative solution is

compress [] = []
compress [a] = [a]
compress (x : y : xs) = (if x == y then [] else [x]) ++ compress (y : xs)

おう,長いやんけ.
groupが謎なんだけど,とりあえず,mapについて調べる.

map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs
http://haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/src/GHC-Base.html#map

よし,非常にわかりやすい.リストの各要素にfをかけるってことだな.
で,謎なのがgroup.WinHugsで実行してみても,Undefinedとか言われちゃう.
たぶん,WinHugsには含まれてないんだろう.かといって,GHCiでも実行できない.なのにググるでてくる.もうやだ,よくわからん.
無視!!
で,

compress [] = []
compress [a] = [a]
compress (x : y : xs) = (if x == y then [] else [x]) ++ compress (y : xs)

は,少しだけ,僕のつくったのと似てる.でもこっちのほうがわかりやすくていいな.同じ場合は,[]でスルーして,違う場合だけ残すって感じか.しかたないけど,若干くやしい.


おわり.

1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all
Ninety-Nine Haskell Problems