Haskell <<loop>> - list

With getIndex xs y I want the index of the first sublist in xs whose length is greater than y.
The output is:
[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
aufgabe6: <<loop>>
why getIndex does not work?
import Data.List
-- Die Sortierfunktion --
myCompare a b
| length a < length b = LT
| otherwise = GT
sortList :: [[a]] -> [[a]]
sortList x = sortBy myCompare x
-- Die Indexfunktion --
getIndex :: [[a]] -> Int -> Int
getIndex [] y = 0
getIndex (x:xs) y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList (x:xs)
main = do
print (sortList [[4],[3,5,3],[4,3],[3,5,5,6,1],[]])
print (getIndex [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2)

Getting it to terminate
The problem is in this case
getIndex (x:xs) y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList (x:xs)
You're confusing which (x:xs) is which. You should instead do
getIndex zs y
| length x <= y = 1 + getIndex xs y
| otherwise = 0
where (x:xs) = sortList zs
giving
Main> main
[[],[4],[4,3],[3,5,3],[3,5,5,6,1]]
3
*Main> getIndex [[],[2],[4,5]] 1
2
*Main> getIndex [[],[2],[4,5]] 5
3
This gives you the number of the first list of length at least y in the sorted list, which actually answers the question "How many lists are of length at most y in the original?"
How can we find out other facts?
If you want position from the original list, you can tag the entries with their position, using zip:
*Main> zip [1..] [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
[(1,[4]),(2,[3,5,3]),(3,[4,3]),(4,[3,5,5,6,1]),(5,[])]
Let's make a utility function for working with those:
hasLength likeThis (_,xs) = likeThis (length xs)
We can use it like this:
*Main> hasLength (==4) (1,[1,2,3,4])
True
*Main> filter (hasLength (>=2)) (zip [1..] ["","yo","hi there","?"])
[(2,"yo"),(3,"hi there")]
Which means it's now easy to write a function that gives you the index of the first list of length longer than y:
whichIsLongerThan xss y =
case filter (hasLength (>y)) (zip [1..] xss) of
[] -> error "nothing long enough" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
This gives us
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
2
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 3
4
*Main> whichIsLongerThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
1
Shorter?
but we can do similar tricks:
whichIsShorterThan xss y =
case filter (hasLength (<y)) (zip [1..] xss) of
[] -> error "nothing short enough" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
so you get
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 2
1
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 1
5
*Main> whichIsShorterThan [[4],[3,5,3],[4,3],[3,5,5,6,1],[]] 0
*** Exception: nothing short enough
Generalised
Let's pull out the common theme there:
whichLength :: (Int -> Bool) -> [[a]] -> Int
whichLength likeThis xss =
case filter (hasLength likeThis) (zip [1..] xss) of
[] -> error "nothing found" -- change this to 0 or (length xss + 1) if you prefer
(x:xs) -> fst x
so we can do
*Main> whichLength (==5) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
4
*Main> whichLength (>2) [[4],[3,5,3],[4,3],[3,5,5,6,1],[]]
2

Do you mean index of the firs sublist with length > y? If that's not the goal (and < y is), then
length x <= y = 1 + getIndex xs y
should be
length x >= y = 1 + getIndex xs y
Also, (x:xs) = sortList (x:xs) is bottom, since it will never end. If you want to sort it somehow, you might follow AndrewC's solution.

let (and where) bindings in Haskell are recursive: LHS and RHS both belong (and thus refer to) to the same new scope. Your code is equivalent to
........
getIndex (x:xs) y =
let -- new, extended scope, containing definitions for
(x:xs) = a -- new variables x, xs, a ... the original vars x, xs
a = sortList a -- are inaccessible, __shadowed__ by new definitions
in -- evaluated inside the new, extended scope
if length x <= y -- x refers to the new definition
then 1 + getIndex xs y
else 0
When the value of x is demanded by length, its new definition (x:xs) = a demands the value of a, which is directly defined in terms of itself, a = sortList a:
a = sortList a
= sortList (sortList a)
= sortList (sortList (sortList a))
= sortList (sortList (sortList (sortList a)))
= ....
A black hole.

Related

Count non-empty lists in a lists of lists

I am trying to count the number of non-empty lists in a list of lists with recursive code.
My goal is to write something simple like:
prod :: Num a => [a] -> a
prod [] = 1
prod (x:xs) = x * prod xs
I already have the deifniton and an idea for the edge condition:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [[]] = 0
I have no idea how to continue, any tips?
I think your base case, can be simplified. As a base-case, we can take the empty list [], not a singleton list with an empty list. For the recursive case, we can consider (x:xs). Here we will need to make a distinction between x being an empty list, and x being a non-empty list. We can do that with pattern matching, or with guards:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = -- …
That being said, you do not need recursion at all. You can first filter your list, to omit empty lists, and then call length on that list:
nonEmptyCount :: [[a]] -> Int
nonEmptyCount = length . filter (…)
here you still need to fill in ….
Old fashion pattern matching should be:
import Data.List
nonEmptyCount :: [[a]] -> Int
nonEmptyCount [] = 0
nonEmptyCount (x:xs) = if null x then 1 + (nonEmptyCount xs) else nonEmptyCount xs
The following was posted in a comment, now deleted:
countNE = sum<$>(1<$)<<<(>>=(1`take`))
This most certainly will look intimidating to the non-initiated, but actually, it is equivalent to
= sum <$> (1 <$) <<< (>>= (1 `take`))
= sum <$> (1 <$) . (take 1 =<<)
= sum . fmap (const 1) . concatMap (take 1)
= sum . map (const 1) . concat . map (take 1)
which is further equivalent to
countNE xs = sum . map (const 1) . concat $ map (take 1) xs
= sum . map (const 1) $ concat [take 1 x | x <- xs]
= sum . map (const 1) $ [ r | x <- xs, r <- take 1 x]
= sum $ [const 1 r | (y:t) <- xs, r <- take 1 (y:t)] -- sneakiness!
= sum [const 1 r | (y:_) <- xs, r <- [y]]
= sum [const 1 y | (y:_) <- xs]
= sum [ 1 | (_:_) <- xs] -- replace each
-- non-empty list
-- in
-- xs
-- with 1, and
-- sum all the 1s up!
= (length . (take 1 =<<)) xs
= (length . filter (not . null)) xs
which should be much clearer, even if in a bit sneaky way. It isn't recursive in itself, yes, but both sum and the list-comprehension would be implemented recursively by a given Haskell implementation.
This reimplements length as sum . (1 <$), and filter p xs as [x | x <- xs, p x], and uses the equivalence not (null xs) === (length xs) >= 1.
See? Haskell is fun. Even if it doesn't yet feel like it, but it will be. :)

How to add values from two lists (+extra condition) in Haskell

I got a problem with this exercise. I've been trying to solve it for a long time searching for stuff, but I am unable to.
Define functions:
addLnat :: [Int] -> [Int] -> [Int]
mulLnat :: [Int] -> [Int] -> [Int]
addLnat adds numbers from two arrays eg.
addLnat [4,5,6] [8,5,2] -> [2,1,9]
as [4+8 gives 2 carry 1, 5+5+1 gives 1 carry 1, 6+2+1 = 9]
Lnat, is a "list natural number", represented as a list of base-10 digits, least significant first. So the number 654 is [4,5,6].
What I got is:
addLnat :: [Int] -> [Int] -> [Int]
addLnat _ [] = []
addLnat [] _ = []
addLnat (x:xs) (y:ys) = (if (x+y) > 9 then x+y-10 else (x+y)):(addLnat xs ys)
I adding number and ignoring carry. Not sure how to solve it.
Any help would be much appreciated.
I have improved the solution as per user5402 comment, so created addLnat' cr xs ys, but when I what to pass carry as a parameter it fails to load - most probable that I am getting the syntax wrong:(
(cr is 0 only for now and it will be replaced by maths).
addLnat' c (x:xs) (y:ys) = d : addLnat' cr xs ys
where d = if c+x+y < 9 then x+y else c+x+y-((quot (c+x+y) 10)*10)
cr = 0
Any ideas?
I am not very good at haskell but maybe this can help ;
add::[Int]->[Int]->[Int]
add x y = add' 0 x y
There we define a function add that will use add' to add two lists The main idea is to "save" carry and carefully work with corner cases. Here carry is saved in "variable" rest
add'::Int->[Int]->[Int]->[Int]
add' 0 x [] = x
add' rest (x:[]) (y:[]) = [(r `mod` 10),(r `div` 10)]
where r = x+y+rest
add' y (x:xs) [] = add' (r `div` 10) ((r `mod` 10):xs) []
where r = x+y
add' rest (x:xs) (y:ys) = (r `mod` 10) : (add' (r `div` 10) xs ys)
where r = x+y+rest
List x must be bigger than list y but that's not a problem
add [5,7,8] [4,3,2] => [9,0,1,1] (correct)
add [1,2,3] [4,5,6] => [5,7,9,0] (correct)
You need to write a version of addLnat which accepts a carry parameter:
addLnat' c (x:xs) (y:ys) = d : addLnat c' xs ys
where d = if c+x+y > 9 then ... else ...
c' = ... the next carry bit ...
There are a lot more details and corner cases to consider, but this is the basic idea.
Finally,
addLnat xs ys = addLnat' 0 xs ys -- initially the carry is 0

haskell list and functional

This is homework that has been driving crazy for the last couple of days.
I got a list that I am applying a function to - pushing each element to the right if the element next to it is smaller then the previous one.
My function to pass over the list once and sort the head of the list:
sortEm lis#(x:y:xs) = if x > y then y: sortEm (x:xs) else lis
sortEm [x] = [x]
sortEm [] = []
myList (x:y:xs) = if x > y then sortEm lis else x:myList(y:xs)
myList [] = []
myList [x] = [x]
But my problem is that once that sortem has finished it returns either an empty list or a list containing one element, how would i design this the functional way?
I was thinking about foldl and some haskell magic to go along with that but currently I am stuck.
Thanks in advance
First of, your sortEm function name is misleading, it doesn't sort its argument list but inserts its head element into its tail. As it happens, there is an insert function already in Data.List module that inserts its first argument into the 2nd, so there's an equivalency
sortEm (x:xs) === Data.List.insert x xs
Now, inserting an item will only get you a sorted list back if you're inserting it into a list that is already sorted. Since empty list is sorted, that's what myList function does that you got in dave4420's answer. That is an "insertion" sort, progressively inserting elements of list into an auxiliary list, initially empty. And that's what the 2nd function does that you got in dave4420 answer:
insertionSort xs = foldr Data.List.insert [] xs
This does "apply sortem" i.e. inserts, "each element" only once. For a list [a,b,c,...,z] it's equivalent to
insert a (insert b (insert c (... (insert z []) ...)))
What you probably meant in your comment, i.e. comparing (and possibly swapping) two neighboring elements "only once", is known as bubble sort. Of course making only one pass through the list won't get it sorted, in a general case:
bubbleOnce xs = foldr g [] xs where
g x [] = [x]
g x xs#(y:ys) | x>y = y:x:ys -- swap x and y in the output
| otherwise = x:xs -- keep x before y in the output
Now, bubbleOnce [4,2,6,1,8] ==> [1,4,2,6,8]. The value that you expected, [2,4,1,6,8], would result from applying the folding function g in an opposite direction, from the left to the right. But that's much less natural to do here with Haskell lists:
bubbleOnce' [] = []
bubbleOnce' (x:xs) = let (z,h)=foldl g (x,id) xs in (h [z]) where
g (x,f) y | x>y = (x, f.(y:)) -- swap x and y in the output
| otherwise = (y, f.(x:)) -- keep x before y in the output
(edit:) see jimmyt's answer for the equivalent, but simple and nice version using straightforward recursion. It is also lazier (less strict) than both the fodlr and foldl versions here.
myList [] = []
myList (x : xs) = sortEm (x : myList xs)
(untested)
Or in terms of a fold:
myList = foldr cons []
where cons x xs = sortEm (x : xs)
(also untested)
-- if..then..else version
sortEM :: Ord a => [a] -> [a]
sortEM (x:y:xs) = if x < y
then x : sortEM (y:xs)
else y : sortEM (x:xs)
sortEM b = b
-- guard version
sortEM_G :: Ord a => [a] -> [a]
sortEM_G (x:y:xs)
| x < y = x : sortEM_G (y:xs)
| otherwise = y : sortEM_G (x:xs)
sortEM_G b = b

Comparing lists in Haskel

I have to define a function called zeros which takes input of two lists and returns a boolean which returns True if the number 0 appears the same amount of times in each list and false otherwise.
This is the last question in my homework and and I have managed to solve the question get it to work but I wondered if anybody can spot ways in which to reduce the amount of code, any ideas are appreciated. My code so far is as follows:
x :: Int
x = 0
instances::[Int]->Int
instances [] = 0
instances (y:ys)
| x==y = 1+(instances ys)
| otherwise = instances ys
zeros :: [Int] -> [Int] -> Bool
zeros [] [] = False
zeros x y
| ((instances x) == (instances y)) = True
| otherwise = False
Without giving too much away, since this is homework, here are a few hints.
Do you know about list comprehensions yet? They would be useful in this case. For example, you could combine them with an if expression to do something like this:
*Main> let starS s = [if c == 's' then '*' else ' ' | c <- s]
*Main> starS "schooners"
"* *"
You can even use them to do filtering. For example:
*Main> let findFives xs = [x | x <- xs, x == 5]
*Main> findFives [3,7,5,6,3,4,5,7,5,5]
[5,5,5,5]
Neither of these is a complete answer, but it shouldn't be hard to see how to adapt these structures to your situation.
You should also think about whether you actually need a guard here! For example, here's a function written with a guard in the same style as yours:
lensMatch [] [] = True
lensMatch xs ys
| ((length xs) == (length ys)) = True
| otherwise = False
Here's a function that does the same thing!
lensMatch' xs ys = length xs == length ys
You can see that they are the same; testing the first:
*Main> lensMatch [1..4] [1..4]
True
*Main> lensMatch [1..4] [1..5]
False
*Main> lensMatch [] [1..5]
False
*Main> lensMatch [] []
True
And testing the second:
*Main> lensMatch' [1..4] [1..4]
True
*Main> lensMatch' [1..4] [1..5]
False
*Main> lensMatch' [] [1..5]
False
*Main> lensMatch' [] []
True
Finally, I agree very strongly with sblom's comment above; zeros [] [] should be True! Think about the following statement: "For each item x in set s, x > 0". If set s is empty, then the statement is true! It's true because there are no items in s at all. This seems to me like a similar situation.
I can't believe nobody has suggested to use foldr yet. Not the shortest or best definition, but IMO the most educational:
instances :: Eq a => a -> [a] -> Int
instances n = foldr incrementIfEqual 0
where incrementIfEqual x subtotal
| x == n = subtotal + 1
| otherwise = subtotal
zeros :: Num a => [a] -> [a] -> Bool
zeros xs ys = instances 0 xs == instances 0 ys
Though for a really brief definition of instances, what I came up with is basically the same as Abizern:
instances :: Eq a => a -> [a] -> Int
instances x = length . filter (==x)
Have you thought of doing this in one pass by filtering each list to get just the zeroes and then comparing the length of the lists to see if they are equal?
zeroCompare xs ys = cZeroes xs == cZeroes ys
where
cZeroes as = length $ filter (== 0) as
Instead of length and filter, you can take the result of a predicate p, convert it to 0 or 1, and sum the result:
count p = sum . map (fromEnum.p)
--or
import Data.List
count p = foldl' (\x -> (x+).fromEnum.p) 0
In your case, p is of course (==0). Converting Bool to Int using fromEnum is a very useful trick.
Another idea would be to deal with both list simultaneously, which is a little bit lengthy, but easy to understand:
zeros xs ys = cmp xs ys == 0 where
cmp (0:xs) ys = cmp xs ys + 1
cmp xs (0:ys) = cmp xs ys - 1
cmp (_:xs) ys = cmp xs ys
cmp xs (_:ys) = cmp xs ys
cmp [] [] = 0
I would break the problem down into smaller problems involving helper functions.
This is how I would break it down:
Main function to compare two counts
Count helper function
First: You need a way to count the amount of zeroes in a list. For example, I would approach this by doing the following if searching for the number of 0 in an integer list:
count :: [Int] -> Int
count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
Second: You need a way to compare the count of two lists. Essentially, you need a function that takes two lists in as parameters, calculates the count of each list, and then returns a boolean depending on the result. For example, if each list is an int list, corresponding with my count example above:
equalZeroes :: [Int] -> [Int] -> Bool
equalZeroes x y = (count x) == (count y)
You could also define count under the where keyword inside the equalZeroes function like so:
equalZeroes :: [Int] -> [Int] -> Bool
equalZeroes x y = (count x) == (count y)
where
count :: [Int] -> Int
count xs = foldl (\count num -> if num == 0 then (count + 1) else count) 0 xs
When running this code, calling the function as so would get the desired boolean values returned:
equalZeroes [0,1,4,5,6] [1,4,5,0,0]
-> False
equalZeroes [0,1,4,5,6] [1,4,5,0]
-> True

how to modify the i-th element of a Haskell List?

I'm looking for a way to modify the i-th element of haskell List. let says foobar is such a function, then the following works.
let xs = ["a","b","c","d"]
foobar xs 2 "baba" -- xs = ["a","b","baba","d"]
thanks for any reply!
You can do it with splitAt:
Prelude> let xs = ["a","b","c","d"]
Prelude> (\(l,_:r)->l++"baba":r) $ splitAt 2 xs
["a","b","baba","d"]
let xs = ["a","b","c","d"]
take 2 xs ++ ["baba"] ++ drop 3 xs
change n x = zipWith (\k e -> if k == n then x else e) [0..]
A simple function to do it directly:
replaceAt _ _ [] = []
replaceAt 0 x (_:ys) = x:ys
replaceAt n x (y:ys) = y:replaceAt (n - 1) x ys