https://wiki.haskell.org/api.php?action=feedcontributions&user=Giu&feedformat=atomHaskellWiki - User contributions [en]2020-09-29T15:30:20ZUser contributionsMediaWiki 1.27.4https://wiki.haskell.org/index.php?title=99_questions/Solutions/18&diff=3653699 questions/Solutions/182010-08-18T15:59:25Z<p>Giu: Updated my solution to a more paranoid one</p>
<hr />
<div>(**) Extract a slice from a list.<br />
<br />
Given two indices, i and k, the slice is the list containing the elements between the i'th and k'th element of the original list (both limits included). Start counting the elements with 1.<br />
<br />
<haskell><br />
slice xs (i+1) k = take (k-i) $ drop i xs<br />
</haskell><br />
<br />
The same solution as above, but the more paranoid (maybe too paranoid?) version of it (uses guards and Maybe):<br />
<br />
<haskell><br />
slice :: [a] -> Int -> Int -> Maybe [a]<br />
slice [] _ _ = Just []<br />
slice xs k n | k == n = Just []<br />
| k > n || k > length xs || n > length xs || k < 0 || n < 0 = Nothing<br />
| k == 0 = Just (take n xs)<br />
| otherwise = Just (drop (k-1) $ take n xs)<br />
</haskell><br />
<br />
Or, an iterative solution:<br />
<br />
<haskell><br />
slice :: [a]->Int->Int->[a]<br />
slice lst 1 m = slice' lst m []<br />
where<br />
slice' :: [a]->Int->[a]->[a]<br />
slice' _ 0 acc = reverse acc<br />
slice' (x:xs) n acc = slice' xs (n - 1) (x:acc)<br />
slice (x:xs) n m = slice xs (n - 1) (m - 1)<br />
</haskell><br />
<br />
Or:<br />
<br />
<haskell><br />
slice :: [a] -> Int -> Int -> [a]<br />
slice (x:xs) i k<br />
| i > 1 = slice xs (i - 1) (k - 1)<br />
| k < 1 = []<br />
| otherwise = x:slice xs (i - 1) (k - 1)<br />
</haskell><br />
<br />
Another way using <hask>splitAt</hask>, though not nearly as elegant as the <hask>take</hask> and <hask>drop</hask> version:<br />
<br />
<haskell><br />
slice :: [a] -> Int -> Int -> [a]<br />
slice xs i k = chunk<br />
where chop = snd $ splitAt i' xs -- Get the piece starting at i<br />
chunk = fst $ splitAt (k - i') chop -- Remove the part after k<br />
i' = i - 1<br />
</haskell></div>Giuhttps://wiki.haskell.org/index.php?title=99_questions/Solutions/20&diff=3653599 questions/Solutions/202010-08-18T15:34:06Z<p>Giu: Added another solution that also indicates failure using Maybe (thanks to zygoloid from #haskell for the input regarding Maybe)</p>
<hr />
<div>(*) Remove the K'th element from a list.<br />
<br />
<haskell><br />
removeAt :: Int -> [a] -> (a, [a])<br />
removeAt k xs = case back of<br />
[] -> error "removeAt: index too large"<br />
x:rest -> (x, front ++ rest)<br />
where (front, back) = splitAt k xs<br />
</haskell><br />
<br />
Simply use the <hask>splitAt</hask> to split after k elements.<br />
If the original list has fewer than k+1 elements, the second list will be empty, and there will be no element to extract.<br />
Note that the Prolog and Lisp versions treat 1 as the first element in the list, and the Lisp version appends NIL elements to the end of the list if k is greater than the list length.<br />
<br />
or <br />
<br />
<haskell><br />
removeAt n xs = (xs!!n,take n xs ++ drop (n+1) xs)<br />
</haskell><br />
<br />
Another solution that avoids throwing an error and using ++ operators. Treats 1 as the first element in the list.<br />
<br />
<haskell><br />
removeAt :: Int -> [a] -> (Maybe a, [a])<br />
removeAt _ [] = (Nothing, [])<br />
removeAt 1 (x:xs) = (Just x, xs)<br />
removeAt k (x:xs) = let (a, r) = removeAt (k - 1) xs in (a, x:r)<br />
</haskell><br />
<br />
Another solution that also uses Maybe to indicate failure:<br />
<br />
<haskell><br />
removeAt :: Int -> [a] -> (Maybe a, [a]) <br />
removeAt _ [] = (Nothing, [])<br />
removeAt 0 xs = (Nothing, xs)<br />
removeAt nr xs | nr > length xs = (Nothing, xs)<br />
| otherwise = (Just (xs !! nr), fst splitted ++ (tail . snd) splitted)<br />
where splitted = splitAt nr xs<br />
</haskell></div>Giuhttps://wiki.haskell.org/index.php?title=99_questions/Solutions/18&diff=3653399 questions/Solutions/182010-08-18T13:00:57Z<p>Giu: I've come up with a solution that actually is an extended version of the 1st solution</p>
<hr />
<div>(**) Extract a slice from a list.<br />
<br />
Given two indices, i and k, the slice is the list containing the elements between the i'th and k'th element of the original list (both limits included). Start counting the elements with 1.<br />
<br />
<haskell><br />
slice xs (i+1) k = take (k-i) $ drop i xs<br />
</haskell><br />
<br />
The same solution as above, but with guards:<br />
<br />
<haskell><br />
slice [] _ _ = []<br />
slice xs k n | k == n = []<br />
| k > n = error "k > n"<br />
| k == 0 = take n xs<br />
| otherwise = drop (k-1) $ take n xs<br />
</haskell><br />
<br />
Or, an iterative solution:<br />
<br />
<haskell><br />
slice :: [a]->Int->Int->[a]<br />
slice lst 1 m = slice' lst m []<br />
where<br />
slice' :: [a]->Int->[a]->[a]<br />
slice' _ 0 acc = reverse acc<br />
slice' (x:xs) n acc = slice' xs (n - 1) (x:acc)<br />
slice (x:xs) n m = slice xs (n - 1) (m - 1)<br />
</haskell><br />
<br />
Or:<br />
<br />
<haskell><br />
slice :: [a] -> Int -> Int -> [a]<br />
slice (x:xs) i k<br />
| i > 1 = slice xs (i - 1) (k - 1)<br />
| k < 1 = []<br />
| otherwise = x:slice xs (i - 1) (k - 1)<br />
</haskell><br />
<br />
Another way using <hask>splitAt</hask>, though not nearly as elegant as the <hask>take</hask> and <hask>drop</hask> version:<br />
<br />
<haskell><br />
slice :: [a] -> Int -> Int -> [a]<br />
slice xs i k = chunk<br />
where chop = snd $ splitAt i' xs -- Get the piece starting at i<br />
chunk = fst $ splitAt (k - i') chop -- Remove the part after k<br />
i' = i - 1<br />
</haskell></div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36532User:Giu2010-08-18T11:57:07Z<p>Giu: </p>
<hr />
<div>I'm just another Haskell and functional programming novice. <br />
<br />
Somewhere during the year 2009 I decided to make the first steps into the functional programming world by learning Haskell, and I made a superficial excursion in ''this world'' since then.<br />
<br />
In late July 2010 I decided to delve more into the language, and I'm now ''consequently'' learning and using both the language and the functional programming paradigm, and I'm really enjoying it.</div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36530User:Giu2010-08-18T09:04:20Z<p>Giu: </p>
<hr />
<div>I'm just another Haskell and functional programming novice. <br />
<br />
Somewhere during the year 2009 I decided to make the first steps into the functional programming world by learning Haskell, and I made a superficial excursion in ''this world'' since then.<br />
<br />
In late July 2010 I decided to delve more into the language, and since then I'm now ''consequently'' learning and using both the language and the functional programming paradigm, and I'm really enjoying it.</div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36527User:Giu2010-08-18T06:50:03Z<p>Giu: </p>
<hr />
<div>I'm just another Haskell and functional programming novice. <br />
<br />
Somewhere during the year 2009 I decided to make the first steps into the functional programming world by learning Haskell, and I made a superficial excursion in ''this world'' back then.<br />
<br />
In late July 2010 I decided to delve more into the language, and since then I'm now ''consequently'' learning and using both the language and the functional programming paradigm, and I'm really enjoying it.</div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36526User:Giu2010-08-18T06:24:41Z<p>Giu: </p>
<hr />
<div>I'm just another Haskell and functional programming novice. <br />
<br />
I'm consequently learning the language and the functional programming paradigm since August 2010, but I already made multiple superficial excursions in ''this world'' a year ago.</div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36525User:Giu2010-08-18T05:45:58Z<p>Giu: </p>
<hr />
<div>Just another Haskell novice. I've started to learn Haskell (consequently) in August 2010.</div>Giuhttps://wiki.haskell.org/index.php?title=99_questions/Solutions/16&diff=3652499 questions/Solutions/162010-08-18T05:43:28Z<p>Giu: Added a new (complicated, maybe ugly) solution. This was my first approach, but after getting to know take and drop, I came up with the same solution as the 3rd one. I thought I may post it anyway</p>
<hr />
<div>(**) Drop every N'th element from a list.<br />
<br />
<haskell><br />
dropEvery :: [a] -> Int -> [a]<br />
dropEvery [] _ = []<br />
dropEvery (x:xs) n = dropEvery' (x:xs) n 1 where<br />
dropEvery' (x:xs) n i = (if (n `divides` i) then<br />
[] else<br />
[x])<br />
++ (dropEvery' xs n (i+1))<br />
dropEvery' [] _ _ = []<br />
divides x y = y `mod` x == 0<br />
</haskell><br />
<br />
An alternative iterative solution:<br />
<br />
<haskell><br />
dropEvery :: [a] -> Int -> [a]<br />
dropEvery list count = helper list count count<br />
where helper [] _ _ = []<br />
helper (x:xs) count 1 = helper xs count count<br />
helper (x:xs) count n = x : (helper xs count (n - 1))<br />
</haskell><br />
<br />
Yet another iterative solution which divides lists using Prelude:<br />
<br />
<haskell><br />
dropEvery :: [a] -> Int -> [a]<br />
dropEvery [] _ = []<br />
dropEvery list count = (take (count-1) list) ++ dropEvery (drop count list) count<br />
</haskell><br />
<br />
A similar approach using guards:<br />
<br />
<haskell><br />
dropEvery :: [a] -> Int -> [a]<br />
dropEvery xs n<br />
| length xs < n = xs<br />
| otherwise = take (n-1) xs ++ dropEvery (drop n xs) n<br />
</haskell><br />
<br />
Using zip:<br />
<br />
<haskell><br />
dropEvery n = map snd . filter ((n/=) . fst) . zip (cycle [1..n])<br />
</haskell><br />
<br />
A more complicated approach which first divides the input list into sublists that do not contain the nth element, and then concatenates the sublists to a result list (if not apparent: the author's a novice):<br />
<haskell><br />
dropEvery :: [a] -> Int -> [a]<br />
dropEvery [] _ = []<br />
dropEvery xs n = concat (split n xs)<br />
where <br />
split _ [] = []<br />
split n xs = fst splitted : split n ((safetail . snd) splitted)<br />
where <br />
splitted = splitAt (n-1) xs<br />
safetail xs | null xs = []<br />
| otherwise = tail xs<br />
</haskell></div>Giuhttps://wiki.haskell.org/index.php?title=User:Giu&diff=36518User:Giu2010-08-16T19:14:42Z<p>Giu: Just some text</p>
<hr />
<div>Just another Haskell novice</div>Giuhttps://wiki.haskell.org/index.php?title=99_questions/Solutions/10&diff=3651799 questions/Solutions/102010-08-16T14:50:06Z<p>Giu: </p>
<hr />
<div>(*) Run-length encoding of a list.<br />
<br />
Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.<br />
<br />
<haskell><br />
encode xs = map (\x -> (length x,head x)) (group xs)<br />
</haskell><br />
<br />
which can also be expressed as a list comprehension:<br />
<br />
<haskell><br />
[(length x, head x) | x <- group xs]<br />
</haskell><br />
<br />
Or writing it [[Pointfree]] (Note that the type signature is essential here to avoid hitting the [[Monomorphism Restriction]]):<br />
<br />
<haskell><br />
encode :: Eq a => [a] -> [(Int, a)]<br />
encode = map (\x -> (length x, head x)) . group<br />
</haskell><br />
<br />
Or (ab)using the "&&&" arrow operator for tuples:<br />
<br />
<haskell><br />
encode :: Eq a => [a] -> [(Int, a)]<br />
encode xs = map (length &&& head) $ group xs<br />
</haskell><br />
<br />
Or with the help of foldr (''pack'' is the resulting function from P09):<br />
<br />
<haskell><br />
encode xs = (enc . pack) xs<br />
where enc = foldr (\x acc -> (length x, head x) : acc) []<br />
</haskell></div>Giuhttps://wiki.haskell.org/index.php?title=99_questions/Solutions/10&diff=3651699 questions/Solutions/102010-08-16T14:46:31Z<p>Giu: Added a solution that makes the usage of foldr</p>
<hr />
<div>(*) Run-length encoding of a list.<br />
<br />
Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as lists (N E) where N is the number of duplicates of the element E.<br />
<br />
<haskell><br />
encode xs = map (\x -> (length x,head x)) (group xs)<br />
</haskell><br />
<br />
which can also be expressed as a list comprehension:<br />
<br />
<haskell><br />
[(length x, head x) | x <- group xs]<br />
</haskell><br />
<br />
Or writing it [[Pointfree]] (Note that the type signature is essential here to avoid hitting the [[Monomorphism Restriction]]):<br />
<br />
<haskell><br />
encode :: Eq a => [a] -> [(Int, a)]<br />
encode = map (\x -> (length x, head x)) . group<br />
</haskell><br />
<br />
Or (ab)using the "&&&" arrow operator for tuples:<br />
<br />
<haskell><br />
encode :: Eq a => [a] -> [(Int, a)]<br />
encode xs = map (length &&& head) $ group xs<br />
</haskell><br />
<br />
Or with the help of foldr:<br />
<br />
<haskell><br />
encode xs = (enc . pack) xs<br />
where enc = foldr (\x acc -> (length x, head x) : acc) []<br />
</haskell></div>Giu