Ninety-Nine Haskell Problems 3
1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all Ninety-Nine Haskell Problems
三問目.
問題.
3 Problem 3
(*) Find the K'th element of a list. The first element in the list is number 1.
Example:
(element-at '(a b c d e) 3)
CExample in Haskell:
Prelude> elementAt [1,2,3] 2
http://www.haskell.org/haskellwiki/99_questions/1_to_10#Problem_3
2
Prelude> elementAt "haskell" 5
'e'
おいおい,これは簡単すぎるじゃないか?というか,昨日見たぞ.
とりあえず,
elementAt x n = x !! (n-1)
は,うまくいく.というか,こんな感じで文字列もリストと同じように扱えるんだ.すごい.
次に,昨日見た!!のソースと似たような定義の仕方.
elementAt' x 1 = head x elementAt' (x:xs) n = elementAt' xs (n-1)
これだけだと,なにも考え付いてないので,さらなる別解を.
なかなか思いつかなかったけど,一行で出来た.
elementAt''' x n = reverse x !! ((length x)-n)
リストを逆転させて数えるっていう.若干まどろっこしいけど.
さて,解答.
Solution: This is (almost) the infix operator !! in Prelude, which is defined as: (!!) :: [a] -> Int -> a (x:_) !! 0 = x (_:xs) !! n = xs !! (n-1) Except this doesn't quite work, because !! is zero-indexed, and element-at should be one-indexed. So: elementAt :: [a] -> Int -> a elementAt list i = list !! (i-1) Or without using the infix operator: elementAt' :: [a] -> Int -> a elementAt' (x:_) 1 = x elementAt' [] _ = error "Index out of bounds" elementAt' (_:xs) k | k < 1 = error "Index out of bounds" | otherwise = elementAt' xs (k - 1)
おやまぁ,長い.でも最初に書いてあるのは!!の定義.で,これをそのまま使うのではだめだから,第二引数の値から1引いて,!!しましょうってこと.僕の一つ目と同じ.よっしゃ.
解答の二つ目も,考え方は同じ.デクリメントしつつリストを削って,ちょうどいいときに「これ!」ってさしだす.
縦線|はkについての条件かな.k<1のときはerror "Index out of bounds"で,それ以外のときはelementAt' xs (k - 1)を実行.
三問目はもうおしまい.これぐらいの分量だと丁度いい.というか,ちょっと物足りない.
でも,思ったのが,「型を明示しよう」ということと,「エラー処理をちゃんとやろう」ということ.エラー処理で甘えるとかいかんね.これが三問目で得たこと.
1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all Ninety-Nine Haskell Problems