Haskell - Find first 0 in a 2 level nested list - list

Imagine you have a 2 dimensional list of lists like this:
[[1, 3, 2, 4, 5, 6, 9, 3], [3, 2, 4, 1, 6, 8, 7, 0, 9], ....]
I want to get the coordinate of the first 0 value of the array -> (1, 7).
I have tried using map and elemIndex.

Both elemIndex and map are quite unnecessary to solve this problem. You simply need to keep track of a set of beginning coordinates and modify it as you recursively transverse the list of lists.
Clearly, the value we're looking for can never be in an empty list, so that case will return Nothing.
If the first list in the list is empty, it also can't be there, so we go to the next list, incrementing the first coordinate and resetting the second to 0.
If that first list is not empty, we check to see if its first element is the one we're looking for. If it is, we can return the coordinates wrapped up with Just, and the recursion ends.
Otherwise, continue by incrementing the second coordinate and considering the remainder of the list of lists.
findCoords :: Eq a => (Int, Int) -> a -> [[a]] -> Maybe (Int, Int)
findCoords _ _ [] = Nothing
findCoords (i, _) v ([]:xs) = findCoords (i+1, 0) v xs
findCoords (i, j) v ((x:y):xs)
| v == x = Just (i, j)
| otherwise = findCoords (i, j+1) v (y:xs)
This requires manually passing (0, 0) when called. This can be cleaned up by using a local aux function.
findCoords :: Eq a => a -> [[a]] -> Maybe (Int, Int)
findCoords = aux (0, 0)
where
aux _ _ [] = Nothing
aux (i, _) v ([]:xs) = aux (i+1, 0) v xs
aux (i, j) v ((x:y):xs)
| v == x = Just (i, j)
| otherwise = aux (i, j+1) v (y:xs)

When you're trying to do something to a number of items, the place to start is to work out how to do that something to just one item. Then map your function across all of the items.
Let's pick this list: [3, 2, 4, 1, 6, 8, 7, 0, 9]
The type of elemIndex can be seen in GHCi by using :t.
:m Data.List -- load module
:t elemIndex -- show type
This returns elemIndex :: Eq a => a -> [a] -> Maybe Int
So, we give it a value and a list and it returns the index as a Maybe.
elemIndex 0 [3, 2, 4, 1, 6, 8, 7, 0, 9] -- returns Just 7
Perhaps we call this function f
f = elemIndex 0
Then we map this function across the list of lists.
result = map f lst
The biggest question is what you mean by the first value. If you have a list like [[1,2,3,0],[0,1,2,3]], which is the first value? That will inform how you process the results of the map.
The way that you handle a Maybe Int, is at the simplest level to match against the two value Just x and Nothing.
f :: Maybe Int -> String
f (Just x) = show x
f Nothing = "Nothing"
main = do
putStrLn $ f (Just 3)
putStrLn $ f (Nothing)
Using these ideas I wrote this code, which appears to do what is required. Having mapped elemIndex over the lists, I find the first matching list using findIndex. The function findIndex takes a predicate for Just x, returning True if so, and False for Nothing. Then it's just a case of matching with Just and Nothing to extract the result.
import Data.List
lst=[[1, 3, 2, 4, 5, 6, 9, 3], [3, 2, 4, 1, 6, 8, 7, 0, 9]]
f = elemIndex 0
pJust :: Maybe a -> Bool
pJust (Just x) = True
pJust Nothing = False
main = do
let results = map f lst
let location = findIndex pJust results
case location of
Just index -> do
let location2 = results !! index
case location2 of
Just index2 -> putStrLn $ "(" ++
show index ++ "," ++
show index2 ++ ")"
Nothing -> putStrLn "Search failed"
Nothing -> putStrLn "Search failed"

Related

How to split a list int groups under certain conditions?

I want to split a list into groups with n elements. For example:
n = 2
[1, 2, 3, 4, 5, 6] ->[[1, 2], [3, 4], [5,6]]
n = 3
[1, 2, 3, 4, 5, 6] -> [[1, 2, 3] [4, 5, 6]]
I tried to implement a function, which returns n if n is 0 or greater than the length of the list and the fitted list if n is less than the length of the list.
split :: Int -> [a] -> Either Int [[a]]
split n [a]
|n <= lenght [a] = Right n (take n [a]) : (split n (drop n [a]))
|n == 0 = Left n
|otherwise = Left n
However, I get a "variable not in scope" error. I've already tried around, but I'm stuck.
Did I make a mistake with the data types?
You have a typo with lenght vs. length, but if we change that there are still errors.
If we look at Right n (take n [a]) we can see that Right and Left only accept a single argument.
Your pattern split n [a] also only matches a list with a single element.
Let's break this down into smaller pieces. Creating a function that splits a list is straightforward.
split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
Prelude> split' 3 [1,2,3,4,5,6]
[[1,2,3],[4,5,6]]
Now it's straightforward to make this local to split to incorporate the checks you specified and return the desired Either type.
split :: Int -> [a] -> Either Int [[a]]
split n [] = Left n
split n lst
| n == 0 || n > length lst = Left n
| otherwise = Right lst'
where
split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
lst' = split' n lst

How can I check which list has the least copies of one element?

I am writing a sudoku Puzzle in Haskell and I have a [[Maybe Int]] where I need to check which of the [Maybe Int] contains the least Nothing elements. In other words, in the following code I should return 1, which is the position of the list with only two Nothing:
newtype Puzzle = Puzzle [[Maybe Int]]
deriving (Show, Eq)
example :: Puzzle
example = [ [Just 3, Just 6, Nothing,Nothing,Just 7, Just 1, Just 2, Nothing,Nothing]
, [Just 7,Just 5, Just 4, Just 9, Just 4, Nothing, Just 1, Just 8, Just 2]
, [Nothing,Nothing,Just 9, Just 2, Nothing,Just 4, Just 7, Nothing,Nothing]
, [Nothing,Nothing,Nothing,Nothing,Just 1, Just 3, Nothing,Just 2, Just 8]
, [Just 4, Nothing,Nothing,Just 5, Nothing,Just 2, Nothing,Nothing,Just 9]
, [Just 2, Just 7, Nothing,Just 4, Just 6, Nothing,Nothing,Nothing,Nothing]
, [Nothing,Nothing,Just 5, Just 3, Nothing,Just 8, Just 9, Nothing,Nothing]
, [Nothing,Just 8, Just 3, Nothing,Nothing,Nothing,Nothing,Just 6, Nothing]
, [Nothing,Nothing,Just 7, Just 6, Just 9, Nothing,Nothing,Just 4, Just 3]
]
[Edit]
I already came up with a solution that does what I want, but this is very slow and inefficient so I am wondering if there is any way to write this in an algorithmically faster way.
nrOfBlanks :: Puzzle -> [Int]
nrOfBlanks sud = map length [ filter isNothing r | r <- rows sud]
whichBlock :: Puzzle -> Maybe Int
whichBlock sud =
whichBlock sud = let i = nrOfBlanks sud
in head(map (\x -> case x of
0 -> elemIndex (foldl1' min (tail i)) i
_ -> elemIndex (foldl1' min i) i) i)
Any help? Thanks in advance!
So you want to find the (index-of) the minimum element according to some metric – in your case number of Nothing elements, but clearly this is a special case of a more general concept: you have some function a -> Int to be used on the elements of an [a] list. In other words, you need a helper with a signature like either
minIndexAccordingTo :: (a -> Int) -> [a] -> Int
or
minimumAccordingTo :: (a -> Int) -> [a] -> a
Something like that is always a good idea to ask Hoogle about. The first one doesn't give useful results, but the second gives as the first two suggestions
maximumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
minimumOn :: (Partial, Ord b) => (a -> b) -> [a] -> a
So, minimumOn is almost exactly what you need. You can import it from the extra package, or here's a definition that only uses base:
import Data.List (sortOn)
minimumOn :: Ord b => (a -> b) -> [a] -> a
minimumOn f = head . sortOn f
Note that even though sorting is O (n · log n), this definition works in linear time thanks to lazyness.
Now, to use this to find an index, you first need to pair your elements with an index, change the metric accordingly, and then throw away the original values at the end:
minimumIndexOn :: Ord b => (a -> b) -> [a] -> Int
minimumIndexOn f = fst . minimumOn (f . snd) . zip [0..]

Haskell remove parenthesis for a tuple

I'm a beginner in Haskell, and this is a question for an assignment.
I'm pretty much done the problem, but I can't figure out how to remove the parenthesis that is surrounding a tuple that I calculated.
get_balance_partition :: Int -> [([Int], [Int])] -> (Int, ([Int], [Int]))
get_balance_partition min (x:xs)
| null xs && difference_partitions x == min = (min, x)
| null xs = (min, ([], []))
| difference_partitions x == min = (min, x)
| otherwise = get_balance_partition min xs
This is a helper function for working code, and I use it like this :
get_balance_partition 2 (two_partitions [7, 4, 3, 6, 10])
output : (2,([7,4,3],[6,10]))
I want to get rid of the parenthesis surrounding the pair of partitions so that the result,
(2,([7,4,3],[6,10]))
looks like
(2,[7,4,3],[6,10])
How can I get rid of the parenthesis when the pair of partitions is stored in x?
There are no standard functions that work on triples, you have to write them yourself.
munge :: (a,(b,c)) -> (a,b,c)
munge (x,(y,z)) = (x,y,z)
munge (get_balance_partition 2 (two_partitions [7, 4, 3, 6, 10]))
Or anonymously as a lambda
(\(x,(y,z)) -> (x,y,z)) (get_balance_partition 2 (two_partitions [7, 4, 3, 6, 10]))
Another way is to modify your definition to match on the tuple in the list directly:
get_balance_partition :: Int -> [([Int], [Int])] -> (Int, ([Int], [Int]))
get_balance_partition min ((x,y):xs)
...
And use (x,y) instead of x everywhere, then you can return e.g. (min, x, y) in the first case, and similarly in other cases.

Filtering a List Haskell

I just started learning Haskell about filtering lists.
Suppose I have the following list : [2, 3, 4, 5, 8, 10, 11]
I would like to keep only those numbers in the list, which are not divisible by the other members.
The result of our example would be : [2, 3, 5, 11]
[x | x <- src, all (\y -> x `rem` y /= 0) (filter (<x) src)]
where src = [2,3,4,5,8,10,11]
It should be noted that you actually also mean dividable by other numbers that are below it, and not just any number in that list, which is why there's a filter in the 2nd argument for all.
The result, of course, is the one you expect in your question: [2,3,5,11].
Here's how it works (and if I'm missing anything, let me know and I'll update).
I'll explain the code side-by-side with normal English. I suggest you just read just the English first, and afterwards see how each statement is expressed in code - I think it should be the most friendly for a newcomer.
Also note that I flipped the arguments for filter and all below (it is invalid!) to make the explanation fluid.
[x|: Construct a list made out of x
x <- src: Where x is an element from src
,: But only the elements that satisfy the following predicate/rule:
all of the numbers from
(filter src (<x)): src that are lesser-than the current x
(\y -> x 'rem' y /= 0): must not yield a remainder equal to 0.
]
For the code part to make sense, make sure you've familiarized yourself with all, filter, rem, and the syntax for: list comprehensions, lambda expressions, sections, and backticks.
On GHC,
Prelude> :m + Data.List
Prelude Data.List> nubBy (\a b -> rem a b == 0) [2,3,4,5,8,10,11]
[2,3,5,11]
does the trick. On Haskell98-compatible systems (e.g. Hugs), use nubBy (\b a -> rem a b == 0).
This answer was posted as a comment by Will Ness.
Using filter
filter :: (a -> Bool) -> [a] -> [a]
and from Data.Numbers.Primes the function
isPrime :: Integral int => int -> Bool
may be
filter isPrime [2, 3, 4, 5, 8, 10, 11]
or using list comprehension
[ x | x <- [2, 3, 4, 5, 8, 10, 11], isPrime x]
change filter predicate as you wish, e.g.
-- None `xs` element (different than `x`) divide `x`
noneDiv xs x = and [x `mod` y /= 0 | y <- xs, x /= y]
now
myFilter xs = filter (noneDiv xs) xs
or
myFilter xs = [x | x <- xs, noneDiv xs x]

Does Haskell have List Slices (i.e. Python)?

Does Haskell have similar syntactic sugar to Python List Slices?
For instance in Python:
x = ['a','b','c','d']
x[1:3]
gives the characters from index 1 to index 2 included (or to index 3 excluded):
['b','c']
I know Haskell has the (!!) function for specific indices, but is there an equivalent "slicing" or list range function?
There's no built-in function to slice a list, but you can easily write one yourself using drop and take:
slice :: Int -> Int -> [a] -> [a]
slice from to xs = take (to - from + 1) (drop from xs)
It should be pointed out that since Haskell lists are singly linked lists (while python lists are arrays), creating sublists like that will be O(to), not O(to - from) like in python (assuming of course that the whole list actually gets evaluated - otherwise Haskell's laziness takes effect).
If you are trying to match Python "lists" (which isn't a list, as others note) then you might want to use the Haskell vector package which does have a built in slice. Also, Vector can be evaluated in parallel, which I think is really cool.
No syntactic sugar. In cases where it's needed, you can just take and drop.
take 2 $ drop 1 $ "abcd" -- gives "bc"
I don't think one is included, but you could write one fairly simply:
slice start end = take (end - start + 1) . drop start
Of course, with the precondition that start and end are in-bounds, and end >= start.
Python slices also support step:
>>> range(10)[::2]
[0, 2, 4, 6, 8]
>>> range(10)[2:8:2]
[2, 4, 6]
So inspired by Dan Burton's dropping every Nth element I implemented a slice with step. It works on infinite lists!
takeStep :: Int -> [a] -> [a]
takeStep _ [] = []
takeStep n (x:xs) = x : takeStep n (drop (n-1) xs)
slice :: Int -> Int -> Int -> [a] -> [a]
slice start stop step = takeStep step . take (stop - start) . drop start
However, Python also supports negative start and stop (it counts from end of list) and negative step (it reverses the list, stop becomes start and vice versa, and steps thru the list).
from pprint import pprint # enter all of this into Python interpreter
pprint([range(10)[ 2: 6], # [2, 3, 4, 5]
range(10)[ 6: 2:-1], # [6, 5, 4, 3]
range(10)[ 6: 2:-2], # [6, 4]
range(10)[-8: 6], # [2, 3, 4, 5]
range(10)[ 2:-4], # [2, 3, 4, 5]
range(10)[-8:-4], # [2, 3, 4, 5]
range(10)[ 6:-8:-1], # [6, 5, 4, 3]
range(10)[-4: 2:-1], # [6, 5, 4, 3]
range(10)[-4:-8:-1]]) # [6, 5, 4, 3]]
How do I implement that in Haskell? I need to reverse the list if the step is negative, start counting start and stop from the end of the list if these are negative, and keep in mind that the resulting list should contain elements with indexes start <= k < stop (with positive step) or start >= k > stop (with negative step).
takeStep :: Int -> [a] -> [a]
takeStep _ [] = []
takeStep n (x:xs)
| n >= 0 = x : takeStep n (drop (n-1) xs)
| otherwise = takeStep (-n) (reverse xs)
slice :: Int -> Int -> Int -> [a] -> [a]
slice a e d xs = z . y . x $ xs -- a:start, e:stop, d:step
where a' = if a >= 0 then a else (length xs + a)
e' = if e >= 0 then e else (length xs + e)
x = if d >= 0 then drop a' else drop e'
y = if d >= 0 then take (e'-a') else take (a'-e'+1)
z = takeStep d
test :: IO () -- slice works exactly in both languages
test = forM_ t (putStrLn . show)
where xs = [0..9]
t = [slice 2 6 1 xs, -- [2, 3, 4, 5]
slice 6 2 (-1) xs, -- [6, 5, 4, 3]
slice 6 2 (-2) xs, -- [6, 4]
slice (-8) 6 1 xs, -- [2, 3, 4, 5]
slice 2 (-4) 1 xs, -- [2, 3, 4, 5]
slice (-8)(-4) 1 xs, -- [2, 3, 4, 5]
slice 6 (-8)(-1) xs, -- [6, 5, 4, 3]
slice (-4) 2 (-1) xs, -- [6, 5, 4, 3]
slice (-4)(-8)(-1) xs] -- [6, 5, 4, 3]
The algorithm still works with infinite lists given positive arguments, but with negative step it returns an empty list (theoretically, it still could return a reversed sublist) and with negative start or stop it enters an infinite loop. So be careful with negative arguments.
I had a similar problem and used a list comprehension:
-- Where lst is an arbitrary list and indc is a list of indices
[lst!!x|x<-[1..]] -- all of lst
[lst!!x|x<-[1,3..]] -- odd-indexed elements of lst
[lst!!x|x<-indc]
Perhaps not as tidy as python's slices, but it does the job. Note that indc can be in any order an need not be contiguous.
As noted, Haskell's use of LINKED lists makes this function O(n) where n is the maximum index accessed as opposed to python's slicing which depends on the number of values accessed.
Disclaimer: I am still new to Haskell and I welcome any corrections.
When I want to emulate a Python range (from m to n) in Haskell, I use a combination of drop & take:
In Python:
print("Hello, World"[2:9]) # prints: "llo, Wo"
In Haskell:
print (drop 2 $ take 9 "Hello, World!") -- prints: "llo, Wo"
-- This is the same:
print (drop 2 (take 9 "Hello, World!")) -- prints: "llo, Wo"
You can, of course, wrap this in a function to make it behave more like Python. For example, if you define the !!! operator to be:
(!!!) array (m, n) = drop m $ take n array
then you will be able to slice it up like:
"Hello, World!" !!! (2, 9) -- evaluates to "llo, Wo"
and use it in another function like this:
print $ "Hello, World!" !!! (2, 9) -- prints: "llo, Wo"
I hope this helps, Jon W.
Another way to do this is with the function splitAt from Data.List -- I find it makes it a little easier to read and understand than using take and drop -- but that's just personal preference:
import Data.List
slice :: Int -> Int -> [a] -> [a]
slice start stop xs = fst $ splitAt (stop - start) (snd $ splitAt start xs)
For example:
Prelude Data.List> slice 0 2 [1, 2, 3, 4, 5, 6]
[1,2]
Prelude Data.List> slice 0 0 [1, 2, 3, 4, 5, 6]
[]
Prelude Data.List> slice 5 2 [1, 2, 3, 4, 5, 6]
[]
Prelude Data.List> slice 1 4 [1, 2, 3, 4, 5, 6]
[2,3,4]
Prelude Data.List> slice 5 7 [1, 2, 3, 4, 5, 6]
[6]
Prelude Data.List> slice 6 10 [1, 2, 3, 4, 5, 6]
[]
This should be equivalent to
let slice' start stop xs = take (stop - start) $ drop start xs
which will certainly be more efficient, but which I find a little more confusing than thinking about the indices where the list is split into front and back halves.
Why not use already existing Data.Vector.slice together with Data.Vector.fromList and Data.Vector.toList (see https://stackoverflow.com/a/8530351/9443841)
import Data.Vector ( fromList, slice, toList )
import Data.Function ( (&) )
vSlice :: Int -> Int -> [a] -> [a]
vSlice start len xs =
xs
& fromList
& slice start len
& toList
I've wrote this code that works for negative numbers as well, like Python's list slicing, except for reversing lists, which I find unrelated to list slicing:
slice :: Int -> Int -> [a] -> [a]
slice 0 x arr
| x < 0 = slice 0 ((length arr)+(x)) arr
| x == (length arr) = arr
| otherwise = slice 0 (x) (init arr)
slice x y arr
| x < 0 = slice ((length arr)+x) y arr
| y < 0 = slice x ((length arr)+y) arr
| otherwise = slice (x-1) (y-1) (tail arr)
main = do
print(slice (-3) (-1) [3, 4, 29, 4, 6]) -- [29,4]
print(slice (2) (-1) [35, 345, 23, 24, 69, 2, 34, 523]) -- [23,24,69,32,34]
print(slice 2 5 [34, 5, 5, 3, 43, 4, 23] ) -- [5,3,43]
Obviously my foldl version loses against the take-drop approach, but maybe someone sees a way to improve it?
slice from to = reverse.snd.foldl build ((from, to + 1), []) where
build res#((_, 0), _) _ = res
build ((0, to), xs) x = ((0, to - 1), x:xs)
build ((from, to), xs) _ = ((from - 1, to - 1), xs)
sublist start length = take length . snd . splitAt start
slice start end = snd .splitAt start . take end