Haskell - Get middle numbers of a list - haskell

I want to reorder a list in the following way:
[5,6,7,8,9] -> [7,5,9,6,8]
[6,7,8,5,4,3] -> [8,5,6,3,7,4]
It's supposed to get the middle number or numbers of the list and put them in the starting position. After that it should start to get the two outer numbers of the list and add them in and work its way in.
I have the following code to get the middle numbers and put them into the beginning of the list but can't figure out how to start adding the outer numbers into the new list.
-- import Data.List
-- import System.IO
longitude xs = length xs
middle xs = length xs `div` 2
addOne xs = middle xs - 1
oneMore xs = length xs - 1
otherCase xs = oneMore xs `div` 2
valuea xs = xs !! middle xs
valueb xs = xs !! addOne xs
valuec xs = xs !! otherCase xs
modulus xs = longitude xs `mod` 2
order xs = midNums xs
takes xs = take (otherCase xs) xs
oddOne xs = otherCase xs + 1
takeX xs = drop (oddOne xs) xs
value xs = takes xs ++ takeX xs
reorder xs = drop (otherCase xs )(take (middle xs + 1) xs)
valueOdd xs = reorder xs ++ takes xs ++ takeX xs
paruno xs = drop (middle xs + 1) xs
pairTwo xs = take (addOne xs) xs
midPair xs = take (addOne xs)(drop (middle xs -1) xs)
--Get the numbers
midNums xs = if modulus xs == 0 then midPair xs ++ paruno xs ++ pairTwo xs
else valueOdd xs
I want it to work like this: Demo

Try this:
f :: (Num a) => [a] -> [a]
f [] = []
f [x] = [x]
f xs = if len `mod` 2 == 1 then flatten [xs !! half] else flatten [xs !! (half-1), xs !! half]
where len = length xs
half = len `div` 2
firsthalf = take (half-1) xs
secondhalf = (reverse . take half . drop (half+1)) xs
outtoin = zipWith (\x y -> x:y:[]) firsthalf secondhalf
flatten = concat . flip (:) outtoin
Breaking it down:
First get the midpoint(s)
Next get the two halves of the list excluding middle elements
Build the list from outside inwards using zip
Concatenate the zip result to flatten and add to the middle elements list
Demo

Related

How to split a list of numbers into a set of list with all the numbers in Haskell

How do i split a list in Haskell, for example, "222 33244" into ["222","33","2","444"] only through recursion and fuctions on the prelude?
My current attempt is:
list xs
|length xs == 0 = ""
|otherwise = listSplit xs
listSplit (x:xs)
|x == head xs = x : ListSplitNext x xs
|otherwise = x:[]
listSplitNext a (x:xs)
|a == x = a : listSplitNext x xs
|otherwise = listSplit xs
So since I don't quite understand your approach and ghci lists 18 compile errors in your code, I'm afraid I can't help you with your attempt at a solution.
As pointed out in a comment, a possible solution would be:
listSplit xs = listSplit' [] (filter (`elem` ['0'..'9']) xs)
listSplit' ws (x:xs) = listSplit' (ws ++ [x : takeWhile (==x) xs]) (dropWhile (==x) xs)
listSplit' ws [] = ws
Filter every element of the string that is not a number (Data.Char.isNumber would do this, too, but the premise was to only use Prelude functions) and call listSplit' on the filtered list.
(ws ++ [x : takeWhile (==x) xs]) collects everything in xs until it reaches a letter that does not equal x, wraps this in a list and appends it to ws.
(dropWhile (==x) xs) removes every letter in xs until it reaches a letter that does not equal x.
Finally, the function calls itself with the updated ws and the reduced xs
If there are no more remaining elements, the function returns ws
If your goal is to use very few pre-defined functions this might give you some ideas:
listSplit :: String -> [String]
listSplit xs =
let (as, a) = foldr go ([], []) numbers
in a : as
where
isNumber x = x `elem` ['0'..'9']
numbers = filter isNumber xs
go cur (res, []) = (res, [cur])
go cur (res, lst#(a:_))
| a == cur = (res, a : lst)
| otherwise = (lst : res, [cur])
Of course you can replace foldr with your own recursion as well:
numberSplit :: String -> [String]
numberSplit xs =
let numbers = filter (`elem` ['0'..'9']) xs
in listSplit numbers
listSplit :: Eq a => [a] -> [[a]]
listSplit =
reverse . go [] []
where
go acc as [] = as : acc
go acc [] (x:xs) = go acc [x] xs
go acc as#(a:_) (x:xs)
| a == x = go acc (a : as) xs
| otherwise = go (as : acc) [x] xs
I had a moment to implement this but I think this is what you're looking for.
listSplit s = go filtered
where filtered = [c | c <- s, elem c ['0'..'9']]
go [] = []
go (x:xs) = (x : takeWhile (== x) xs) : (go $ dropWhile (== x) xs)

haskell mergesort implementation compiles but does not return anything

Here is my implementation:
mergesort :: (Ord a) => [a] -> [a]
mergesort list = merge (mergesort (left list)) (mergesort (right list))
where
left xs = take (div (length xs) 2) xs
right xs = drop (div (length xs) 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys
The code compiles but when I run it my machine crashes. What am I doing wrong?
You are missing base cases - so you get infinite recursion. Trying stepping through your example with lists like [] or [1] and you'll fall straight into the problem.
mergesort :: (Ord a) => [a] -> [a]
mergesort [] = [] -- < ADDED
mergesort [x] = [x] -- < ADDED
mergesort list = merge (mergesort (left list)) (mergesort (right list))
where
left xs = take (div (length xs) 2) xs
right xs = drop (div (length xs) 2) xs
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
| x <= y = x : merge xs (y:ys)
| otherwise = y : merge (x:xs) ys

Problems with understanding splitAt in Haskell?

So I have found that the built-in splitAt function in Haskell can be defined as follows:
splitAt :: Int -> [a] -> ([a], [a])
-- Pre: n >= 0
splitAt n []
= ([], [])
splitAt n (x : xs)
= if n == 0
then ([], x : xs)
else (x : xs', xs'')
where
(xs', xs'') = splitAt (n - 1) xs
What I don't understand here/can't get my head around is the where part.
As an example,
splitAt 2 "Haskell" should return (["Ha"],["skell"]), but I don't really understand how it works here to define (x:xs',xs'') as another function? How would this look like visually?
With the example:
splitAt 2 "Haskell"
= (('H':xs',xs''))
^ so this then does splitAt 1 "askell", but I'm very confused as to what happens to the xs',xs'' in the tuple above...
Thanks.
(xs', xs'') = splitAt (n - 1) xs
This takes the result of splitAt (n - 1) xs, which is a pair, and assigns the name xs' to the first element of that pair (i.e. the first n - 1 elements of xs) and xs'' to the second element (i.e. the remaining elements).
(x:xs', xs'')
This produces a pair. The first element of that pair is a list that's the result of prepending x to xs' (i.e. to the first n-1 elements of xs). The second element is xs'' (i.e. the remaining elements of xs).

Reducing this Haskell function

I want to double every second element of a list. Here is the code-
doubleSec n [] = []
doubleSec n (x:xs)
| n==1 = x*2 : doubleSec 0 xs
| otherwise = x : doubleSec 1 xs
doubleSecond xs =
doubleSec 0 xs
How can I compact this logic in a single function?
You can match a pattern on the list like this
doubleSec :: [Int] -> [Int]
doubleSec [] = []
doubleSec [x] = [x]
doubleSec (x : y : xs) = x : 2* y : doubleSec xs
letting you do specific things to the second element
How about this
doubleSecond xs = map (\(x,i) -> if odd i then x*2 else x) (zip xs [0..])
This method will preserve the O(n) running time:
doubleSecond xs =
[ if isOddStep then 2 * x else x |
(isOddStep, x) <- zip (cycle [False, True]) xs ]
An more succinct version by #DavidFletcher:
doubleSecond = zipWith ($) (cycle [id, (2*)])
or:
doubleSecond = zipWith id (cycle [id, (2*)])
as suggested by #Carl.

Enumerating all pairs of possibly infinite lists [duplicate]

I have a function for finite lists
> kart :: [a] -> [b] -> [(a,b)]
> kart xs ys = [(x,y) | x <- xs, y <- ys]
but how to implement it for infinite lists? I have heard something about Cantor and set theory.
I also found a function like
> genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
But I'm not sure if it helps, because Hugs only gives out pairs without ever stopping.
Thanks for help.
Your first definition, kart xs ys = [(x,y) | x <- xs, y <- ys], is equivalent to
kart xs ys = xs >>= (\x ->
ys >>= (\y -> [(x,y)]))
where
(x:xs) >>= g = g x ++ (xs >>= g)
(x:xs) ++ ys = x : (xs ++ ys)
are sequential operations. Redefine them as alternating operations,
(x:xs) >>/ g = g x +/ (xs >>/ g)
(x:xs) +/ ys = x : (ys +/ xs)
[] +/ ys = ys
and your definition should be good to go for infinite lists as well:
kart_i xs ys = xs >>/ (\x ->
ys >>/ (\y -> [(x,y)]))
testing,
Prelude> take 20 $ kart_i [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(1,103),(2,102),(1,104),(4,101),(1,105),(2,103)
,(1,106),(3,102),(1,107),(2,104),(1,108),(5,101),(1,109),(2,105),(1,110),(3,103)]
courtesy of "The Reasoned Schemer". (see also conda, condi, conde, condu).
another way, more explicit, is to create separate sub-streams and combine them:
kart_i2 xs ys = foldr g [] [map (x,) ys | x <- xs]
where
g a b = head a : head b : g (tail a) (tail b)
this actually produces exactly the same results. But now we have more control over how we combine the sub-streams. We can be more diagonal:
kart_i3 xs ys = g [] [map (x,) ys | x <- xs]
where -- works both for finite
g [] [] = [] -- and infinite lists
g a b = concatMap (take 1) a
++ g (filter (not . null) (take 1 b ++ map (drop 1) a))
(drop 1 b)
so that now we get
Prelude> take 20 $ kart_i3 [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(2,102),(1,103),(4,101),(3,102),(2,103),(1,104)
,(5,101),(4,102),(3,103),(2,104),(1,105),(6,101),(5,102),(4,103),(3,104),(2,105)]
With some searching on SO I've also found an answer by Norman Ramsey with seemingly yet another way to generate the sequence, splitting these sub-streams into four areas - top-left tip, top row, left column, and recursively the rest. His merge there is the same as our +/ here.
Your second definition,
genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
is equivalent to just
genFromPair (e1, e2) = [0*e1 + y*e2 | y <- [0..]]
Because the list [0..] is infinite there's no chance for any other value of x to come into play. This is the problem that the above definitions all try to avoid.
Prelude> let kart = (\xs ys -> [(x,y) | ls <- map (\x -> map (\y -> (x,y)) ys) xs, (x,y) <- ls])
Prelude> :t kart
kart :: [t] -> [t1] -> [(t, t1)]
Prelude> take 10 $ kart [0..] [1..]
[(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9),(0,10)]
Prelude> take 10 $ kart [0..] [5..10]
[(0,5),(0,6),(0,7),(0,8),(0,9),(0,10),(1,5),(1,6),(1,7),(1,8)]
you can think of the sequel as
0: (0, 0)
/ \
1: (1,0) (0,1)
/ \ / \
2: (2,0) (1, 1) (0,2)
...
Each level can be expressed by level n: [(n,0), (n-1, 1), (n-2, 2), ..., (0, n)]
Doing this to n <- [0..]
We have
cartesianProducts = [(n-m, m) | n<-[0..], m<-[0..n]]

Resources