Haskell search an element on a List - haskell

I want a function that changes (1 to 0) on a list of lists, when number of 1's in that line/column isn't even. I have done these functions:
1) Sees if the lines in a list are even or not:
parityLine :: [[Int]] -> [Bool]
parityLine [] =[]
parityLine (x:xs)
|sum(x) `mod` 2 == 0 = True:(parityLine(xs))
|otherwise = False:(parityLine(xs))
2) Sum the corresponding elements on a list of lists:
sumPositions :: [[Int]] -> [Int]
sumPositions [] = []
sumPositions (x:xs) = foldl (zipWith (+)) (repeat 0) (x:xs)
3) Sees if the columns in a list are even or not:
parityColumn :: [Int] -> [Bool]
parityColumn [] = []
parityColumn (x:xs)
|head(x:xs) `mod` 2 == 0 = True:parityColumn(xs)
|otherwise = False:parityColumn(xs)
4) Does the operation or with two boolean lists:
bol :: [Bool] -> [Bool] -> [[Bool]]
bol [] _ = []
bol (x:xs) (y:ys)= (map (||x) (y:ys)):(bol xs (y:ys))
5) Correct List:
correct :: [[Int]] -> [[Bool]]
correct [] = []
correct (x:xs)=(bol(parityLine (x:xs))(parityColumn(sumPositions(x:xs))))
So what I want is to alter the function correct to [[Int]]->[[Int]] that does this:
My Int list(x:xs) With my correct function applied
[[0,0,1,1], [[True,True,True,True],
[1,0,1,1], [True,True,False,True],
[0,1,0,1], [True,True,True,True]
[1,1,1,1]] [True,True,True,True]]
Now I can see that in the second line third column, False, so I have to correct that number 1 to have a number of 1's even. If there is more than one False in that list, I only want to correct one of these 1's.
As a result, I want that function correct returns:
[[0,0,1,1],
[1,0,0,1],
[0,1,0,1],
[1,1,1,1]]
Thanks.

I'll give an answer that starts where you are rather than from scratch, so we're doing it more your way than mine.
First let's do it for a single element:
leaveIf :: Bool -> Int -> Int
leaveIf yes 0 = if yes then 0 else 1
leaveIf yes 1 = if yes then 1 else 0
(You could use guards for that, but my phone doesn't have the vertical bar character!)
Next we can do it for a list of lists:
edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = zipWith (zipWith leaveIf) boolss intss
EDIT: You'd like to only change one, so we'll need a way of making subsequent Falses into Trues:
makeTrue :: [Bool] -> [Bool]
makeTrue xs = map (const True) xs
I've used the function const :: a -> b -> a. For example, const 5 'c' is just 5. I could shorten that definition to makeTrue = map (const True). Once you get used to thinking that way, you'll find the shorter version clearer.
oneFalse :: [[Bool]] -> [[Bool]]
oneFalse [] = []
oneFalse (xs:xss) = let (trues,falses) = break (==False) xs in
case falses of
[] -> trues:oneFalse xss
(False:others) -> (trues ++ False : makeTrue others) : map makeTrue xss
(==False) could be written more simply as not, but less clearly perhaps.
so for example
> oneFalse [[True,True,True,True],[True,False,True,False],[True,False,False,True]]
[[True,True,True,True],[True,False,True,True],[True,True,True,True]]
So now we can have
editOne :: [[Bool]] -> [[Int]] -> [[Int]]
editOne boolss intss = zipWith (zipWith leaveIf) (oneFalse boolss) intss

AndrewC already gave an solution which changed all 1s corresponding to Falses. If we only want to correct the first one, we have to find a replacement for zipWith:
leaveIf ok x = if ok then x else 1 -x
-- Varianto of zipWith, which changes at most one element of the list
modFirst :: Eq b => (a -> b -> b) -> [a] -> [b] -> [b]
modFirst _ [] _ = []
modFirst _ _ [] = []
modFirst f (x:xs) (y:ys) = z : if y == z then modFirst f xs ys else ys
where z = f x y
edit :: [[Bool]] -> [[Int]] -> [[Int]]
edit boolss intss = modFirst (modFirst leaveIf) boolss intss
correct' :: [[Int]] -> [[Int]]
correct' xss = edit (correct' xss) xss
The result is the not necessarily a list of lists where all lines/rows contain an even number of 1's:
correct' [[0,1,0],[1,1,1],[0,1,0]] = [[1,1,0],[1,1,1],[0,1,0]
You need to iterate it a few times, until all errors are fixed (i.e., compute a fixpoint).
I'd like to add that your original program can be simplified quite a bit (without changing your algorithm):
parityLine :: [[Int]] -> [Bool]
parityLine = map (even . sum)
parityColumn :: [Int] -> [Bool]
parityColumn = map even
sumPositions :: [[Int]] -> [Int]
sumPositions = foldl (zipWith (+)) (repeat 0)
bol :: [Bool] -> [Bool] -> [[Bool]]
bol xs ys = map (\x -> map (||x) ys) xs
correct :: [[Int]] -> [[Bool]]
correct xs = bol (parityLine xs) (parityColumn $ sumPositions xs)

Related

Haskell - Non-exhaustive pattern for a reason I don't understand

So I'm trying to write a function that, given two lists of integers, adds the ith even number of each list and returns them in another list. In case one of the list doesn't have an ith even number, a 0 is considered. For example, if the lists are [1,2,1,4,6] and [2,2], it returns [4,6,6] ([2+2,4+2,6+0]). I have the following code:
addEven :: [Int] -> [Int] -> [Int]
addEeven [] [] = []
addEeven (x:xs) [] = filter (\g -> g `mod`2 == 0) (x:xs)
addEven [] (y:ys) = filter (\g -> g `mod` 2 == 0) (y:ys)
addEven (x:xs) (y:ys) = (a + b):(addEven as bs)
where
(a:as) = filter (\g -> g `mod` 2 == 0) (x:xs)
(b:bs) = filter (\g -> g `mod` 2 == 0) (y:ys)
When I run that with the previous example, I get:
[4,6*** Exception: ex.hs:(4,1)-(8,101): Non-exhaustive patterns in function addEven
I really can't see what I'm missing, since it doesn't work with any input I throw at it.
A filter might eliminate elements, hence filter (\g -> gmod2 == 0) is not said to return any elements, and thus the patterns (a:as) and (b:bs) might fail.
That being said, I think you make the problem too complex here. You can first define a helper function that adds two elements of a list:
addList :: Num a => [a] -> [a] -> [a]
addList (x:xs) (y:ys) = (x+y) : addList xs ys
addList xs [] = xs
addList [] ys = ys
Then we do the filter on the two parameters, and make a function addEven that looks like:
addEven :: Integral a => [a] -> [a] -> [a]
addEven xs ys = addList (filter even xs) (filter even ys)
or with on :: (b -> b -> c) -> (a -> b) -> a -> a -> c:
import Data.Function(on)
addEven :: Integral a => [a] -> [a] -> [a]
addEven = addList `on` filter even
While using filter is very instinctive in this case, perhaps using filter twice and then summing up the results might be slightly ineffficient for large lists. Why don't we do the job all at once for a change..?
addMatches :: [Int] -> [Int] -> [Int]
addMatches [] [] = []
addMatches [] ys = filter even ys
addMatches xs [] = filter even xs
addMatches xs ys = first [] xs ys
where
first :: [Int] -> [Int] -> [Int] -> [Int]
first rs [] ys = rs ++ filter even ys
first rs (x:xs) ys = rs ++ if even x then second [x] xs ys
else first [] xs ys
second :: [Int] -> [Int] -> [Int] -> [Int]
second [r] xs [] = [r] ++ filter even xs
second [r] xs (y:ys) = if even y then first [r+y] xs ys
else second [r] xs ys
λ> addMatches [1,2,1,4,6] [2,2]
[4,6,6]

How is map implemented internally?

Ok so i want to implement my custom map that receives a replication factor and a target list.
Inputs: Int -> [Int]
Output: [[Int]]
E.g.: 2 [1,2] -----> [[1,1],[2,2]]
f [1,2,3] -> map -> [f(1),f(2),f(3)]
What is supposed to happen with f(1) when map goes to the next element of the list?How should i replace 1 with f(1) ?
P.S: This was my initial solution but it does replicate the initial list,not every element.
replicate::Int->[Int]->[[Int]]
replicate 1 x=x
replicate factor (x:xs)= go factor [] (x:xs) where
go factor ls (x:xs) =go factor (repl factor x):ls xs
repl 1 nr=nr
repl times nr=nr:repl (times-1) nr
There are two issues, that prevent your code from compiling:
null function has the type [a0] -> Bool, but you're applying it
on an element of a list, hence you're expecting it to be Int -> Bool
The result f x shouldn't be pushed into the tail of the input, it
should be pushed into the result of recursive call of the function:
f x: (mymap f xs) instead of f x: xs
As a result the following code should work:
mymap :: (Int -> [Int]) -> [Int]-> [[Int]]
mymap f (x:xs) = if null xs then [] else f x : (mymap f xs)
By the way, the Standard Library provides much readable (and also polymorphic) implementation using pattern-matching:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
custom map that receives a replication factor and a target list
It is a little unclear to me what you're asking for.
Does mymap receive the replication factor, or does f?
E.g.: 2 [1,2] -----> [[1,1],[2,2]]
If you want mymap 2 [1,2] to give [[1,1],[2,2]], then:
mymap :: Int -> [a] -> [[a]]
mymap = map . replicate
However,
mymap :: (Int -> [Int]) -> [Int] -> [[Int]]
How is this function any different from the built-in map :: (a -> b) -> [a] -> [b] with a as Int and b as [Int]? Here, mymap does not have any Int argument itself, so you must mean that f's argument is the replication factor; but if f 2 3 == [3,3], then f is replicate and you can use the solution above.
You can write this using your own recursive definitions, if you like:
mymap :: Int -> [a] -> [[a]]
mymap _ [] = []
mymap n (x:xs) = myreplicate n x : mymap n xs
myreplicate :: Int -> a -> [a]
myreplicate 0 _ = []
myreplicate n x = x : myreplicate (n-1) x
Or you can use list comprehension instead of a map:
mymap :: Int -> [a] -> [[a]]
mymap n xs = [ replicate n x | x <- xs ]
I'd probably call mymap for replicateMany or something like that.

How to remove second largest element in a list in haskell?

I have created a program to remove first smallest element but I dont how to do for second largest:
withoutBiggest (x:xs) =
withoutBiggestImpl (biggest x xs) [] (x:xs)
where
biggest :: (Ord a) => a -> [a] -> a
biggest big [] = big
biggest big (x:xs) =
if x < big then
biggest x xs
else
biggest big xs
withoutBiggestImpl :: (Eq a) => a -> [a] -> [a] -> [a]
withoutBiggestImpl big before (x:xs) =
if big == x then
before ++ xs
else
withoutBiggestImpl big (before ++ [x]) xs
Here is a simple solution.
Prelude> let list = [10,20,100,50,40,80]
Prelude> let secondLargest = maximum $ filter (/= (maximum list)) list
Prelude> let result = filter (/= secondLargest) list
Prelude> result
[10,20,100,50,40]
Prelude>
A possibility, surely not the best one.
import Data.Permute (rank)
x = [4,2,3]
ranks = rank (length x) x -- this gives [2,0,1]; that means 3 (index 1) is the second smallest
Then:
[x !! i | i <- [0 .. length x -1], i /= 1]
Hmm.. not very cool, let me some time to think to something better please and I'll edit my post.
EDIT
Moreover my previous solution was wrong. This one should be correct, but again not the best one:
import Data.Permute (rank, elems, inverse)
ranks = elems $ rank (length x) x
iranks = elems $ inverse $ rank (length x) x
>>> [x !! (iranks !! i) | i <- filter (/=1) ranks]
[4,2]
An advantage is that this preserves the order of the list, I think.
Here is a solution that removes the n smallest elements from your list:
import Data.List
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
ntails :: Int -> [a] -> [(a, Int)] -> [a]
ntails 0 l _ = l
ntails n l s = ntails (n-1) (deleteN (snd $ head s) l) (tail s)
removeNSmallest :: Ord a => Int -> [a] -> [a]
removeNSmallest n l = ntails n l $ sort $ zip l [0..]
EDIT:
If you just want to remove the 2nd smallest element:
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
remove2 :: [a] -> [(a, Int)] -> [a]
remove2 [] _ = []
remove2 [a] _ = []
remove2 l s = deleteN (snd $ head $ tail s) l
remove2Smallest :: Ord a => [a] -> [a]
remove2Smallest l = remove2 l $ sort $ zip l [0..]
It was not clear if the OP is looking for the biggest (as the name withoutBiggest implies) or what. In this case, one solution is to combine the filter :: (a->Bool) -> [a] -> [a] and maximum :: Ord a => [a] -> a functions from the Prelude.
withoutBiggest l = filter (/= maximum l) l
You can remove the biggest elements by first finding it and then filtering it:
withoutBiggest :: Ord a => [a] -> [a]
withoutBiggest [] = []
withoutBiggest xs = filter (/= maximum xs) xs
You can then remove the second-biggest element in much the same way:
withoutSecondBiggest :: Ord a => [a] -> [a]
withoutSecondBiggest xs =
case withoutBiggest xs of
[] -> xs
rest -> filter (/= maximum rest) xs
Assumptions made:
You want each occurrence of the second-biggest element removed.
When there is zero/one element in the list, there isn't a second element, so there isn't a second-biggest element. Having the list without an element that isn't there is equivalent to having the list.
When the list contains only values equivalent to maximum xs, there also isn't a second-biggest element even though there may be two or more elements in total.
The Ord type-class instance implies a total ordering. Otherwise you may have multiple maxima that are not equivalent; otherwise which one is picked as the biggest and second-biggest is not well-defined.

Haskell-a function that applies a function on a list

I am trying to create a function that accepts a function as parameter, and applies that function on every pair of elements in a list. For example, if I call my function foldPairs, then I would use it as so:
foldPairs (+) [1..10]
[3,7,11,15,19]
I tried using foldl in my attempt...
foldPairs :: (a->a->a) -> [a] -> [a]
foldPairs func lis = foldl func lis
However this clearly does not work. I think I might have to use curried and uncurried but I am not quite sure how. Could someone help me out?
Assuming, that for an odd-numbered input list we just discard the last element, the following will do the required:
foldPairs :: (a->a->a) -> [a] -> [a]
foldPairs _ [] = []
foldPairs _ [_] = []
foldPairs f (x:y:xs) = f x y : foldPairs f xs
The solution I would go with is to turn [1..10] into [[1,2],[3,4],[5,6],[7,8],[9,10]], then filter out any lists of length 1, convert to tuples, then map your function:
chunks :: Int -> [a] -> [[a]]
chunks n = reverse . go []
where
go acc [] = acc
go acc xs =
let (h, t) = splitAt n xs
in go (h:acc) t
Then simply
foldpairs :: (a -> a -> b) -> [a] -> [b]
foldpairs f
= map (uncurry f)
. map (\[x, y] -> (x, y))
. filter ((== 2) . length)
. chunks 2

function that returns a list [0,[x1],[x1,x2],[x1,x2,x3]...] where [x1,x2,x3....] is the original list

How can I make in Haskell a function that gets a list and return a list of lists in this way:
[x1,x2,x3,x4,x5....]
it should return :
[[0],[x1],[x1,x2],[x1,x2,x3],[x1,x2,x3,x4][x1,x2,x3,x4,x5]....]
without using ready function that do it in Haskell.
I assume you mean the empty list [] at the start, not [0].
In which case, it's just inits.
Here's it's definition if you want to write it yourself:
inits xs = [] : case xs of [] -> []
x : xs' -> map (x :) (inits xs')
Assuming you want the empty list at the start:
prefixes :: [a] -> [[a]]
prefixes ls = map (\x -> take x ls) [0..(length ls)]
Code:
import System.IO
transform :: [Int] -> [[Int]]
transform list = trans 0
where trans n = case (length list) >= n of
True -> (take n list):( trans (n+1) )
False -> []
main = do
print . show $ transform [1..7]
Output:
$> ./transform
"[[],[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5],[1,2,3,4,5,6],[1,2,3,4,5,6,7]]"
Edit: To work with Infinite Lists
transform :: [a] -> [[a]]
transform list = trans 0 []
where
trans :: a -> [a] -> [[a]]
trans n last = case last == list of
False -> [take n list]++(trans (n+1) $ take n list)
True -> []

Resources