99 questions/Solutions/17
From HaskellWiki
(Difference between revisions)
(cleanup) |
(Added another solution) |
||
| Line 31: | Line 31: | ||
split xs 0 = ([], xs) | split xs 0 = ([], xs) | ||
split (x:xs) n = let (f,l) = split xs (n-1) in (x : f, l) | split (x:xs) n = let (f,l) = split xs (n-1) in (x : f, l) | ||
| + | </haskell> | ||
| + | |||
| + | A similar solution using foldl: | ||
| + | |||
| + | <haskell> | ||
| + | split :: [a] -> Int -> ([a], [a]) | ||
| + | split [] _ = ([], []) | ||
| + | split list n | ||
| + | | n < 0 = (list, []) | ||
| + | | otherwise = (first output, second output) | ||
| + | where output = foldl (\acc e -> if third acc > 0 then (first acc ++ [e], second acc, third acc - 1) else (first acc, second acc ++ [e], third acc)) ([], [], n) list | ||
| + | </haskell> | ||
| + | |||
| + | Note that for the above code to work you must define your own first, second, and third functions for tuples containing three elements like so: | ||
| + | |||
| + | <haskell> | ||
| + | first :: (a, b, c) -> a | ||
| + | first (x, _, _) = x | ||
| + | |||
| + | second :: (a, b, c) -> b | ||
| + | second (_, y, _) = y | ||
| + | |||
| + | third :: (a, b, c) -> c | ||
| + | third (_, _, z) = z | ||
</haskell> | </haskell> | ||
Revision as of 09:01, 16 November 2011
(*) Split a list into two parts; the length of the first part is given.
Do not use any predefined predicates.
Solution usingtake
drop
split xs n = (take n xs, drop n xs)
splitAt
split = flip splitAt
But these should clearly be considered "predefined predicates". Alternatively, we have the following recursive solution:
split :: [a] -> Int -> ([a], [a]) split [] _ = ([], []) split l@(x : xs) n | n > 0 = (x : ys, zs) | otherwise = ([], l) where (ys,zs) = split xs (n - 1)
The same solution as above written more cleanly:
split :: [a] -> Int -> ([a], [a]) split xs 0 = ([], xs) split (x:xs) n = let (f,l) = split xs (n-1) in (x : f, l)
A similar solution using foldl:
split :: [a] -> Int -> ([a], [a]) split [] _ = ([], []) split list n | n < 0 = (list, []) | otherwise = (first output, second output) where output = foldl (\acc e -> if third acc > 0 then (first acc ++ [e], second acc, third acc - 1) else (first acc, second acc ++ [e], third acc)) ([], [], n) list
Note that for the above code to work you must define your own first, second, and third functions for tuples containing three elements like so:
first :: (a, b, c) -> a first (x, _, _) = x second :: (a, b, c) -> b second (_, y, _) = y third :: (a, b, c) -> c third (_, _, z) = z
