I have a function that returns a list like this:
[ [1, 2, 3], [], [5], [5,6], []]
But I want to replace the empty lists with 0, so that it looks like this
[ [1, 2, 3], [0], [5], [5,6], [0]]
So far I have tried filter and map with little success. Can someone please point me in the right direction?
Here is the code in question:
knightPlace:: [Int] -> [[Int]]
knightPlace n = makeboard n
where
makeboard n = [x | i<-[0..(length n -1 )], x <- [checkPos i]]
-- checkPos add zero
checkPos i = [j+1 | j<-[0..(length n -1 )], queenFilter n i j]
-- filters all rows, cols and diags, also knights
queenFilter n i j = and [n!!(i) == 0 && n!!(k) /=(j+1) && (n!!(k)==0 || (abs(n!!(k)-(j+1))/=abs(i-k))) && (n!!(k)==0 ||not( ((abs(i-k)==2)&& (abs(n!!(k)-(j+1))==1)) ||((abs(i-k)==1)&& (abs(n!!(k)-(j+1))==2)))) | k<-[0..(length n - 1)] ]
Called like
knightPlace [0, 0, 6, 0, 0, 4, 0, 0]
Consider that if you have a function foo that can transform [] to [0] and return every other list untouched, map foo is the final function that you want.
Replace xs with ys in l,
replaceWith :: [a] -> [a] -> [[a]]
replaceWith xs ys l = map (\x -> if x == xs then ys else x) l
In the case here,
replaceWith [] [0] [[1, 2, 3],[],[5],[5,6],[]]
Change your function with
knightPlace n = map (\x -> if null x then [0] else x) $ makeboard n
Also consider using pointfree style
knightPlace = map (\x -> if null x then [0] else x) . makeboard
Related
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
I have a list of 9 integers with values 1, -1, 0 such as:
[-1, 0, 0, 1, -1, -1, 1, 1, 0]
What I am trying to do is that from this one list create list of lists where each one of them contain only one change and all the time different. For each -1 I want to change it into 0.
Example:
From the list:
[-1,0,0,1,-1,-1,1,1,0],
I want to get the result:
[ [ 0, 0, 0, 1, -1, -1, 1, 1, 0]
, [-1, 0, 0, 1, 0, -1, 1, 1, 0]
, [-1, 0, 0, 1, -1, 0, 1, 1, 0]
]
So each list has only one value changed and each has a different one. I have no idea how to even start.
First thing you always need is to figure out the type signature of your function. In your case you want
lister :: [Int] -> [[Int]]
Then, as you want to loop through the list but keeping track of the indexes you have changed, an easy way would be to list a list of your list (hard to follow, just look at the code) and then zip it with its index. Then for each list you switch the element in that position. This is you code
lister :: [Int] -> [[Int]]
lister ls = [switch i l | (i,l) <- zip [0..9] (repeat ls)]
You then need a switch function, to switch the element in the ith position accordingly to your rule:
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Note that this returns 9 lists, one for each element in your original list. Therefore it contains some duplicates. You can eliminate them using nub from Data.List, watch out because it is O(n^2)
This is your complete code:
import Data.List
lister :: [Int] -> [[Int]]
lister ls = nub [switch i l | (i,l) <- zip [0..9] (repeat ls)]
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Clearly this is a very specific problem. It is often useful to look at the bigger picture: what more general problem is this a special case of? Clearly, here, we are looking through a list, and may see an element that we wish to replace, in zero or more ways. Further, we wish to see how many ways it is possible to make a limited number of such replacements. So, let us implement the general case before thinking about how to specialize to our original problem:
import Control.Applicative (Alternative, empty, (<|>))
replaceNTimes :: Alternative f => (a -> f a) -> Int -> [a] -> f [a]
replaceNTimes _ 0 xs = pure xs
replaceNTimes _ _ [] = empty
replaceNTimes f n (x:xs) = replaceHere <|> keepLooking
where replaceHere = (:) <$> f x <*> replaceNTimes f (n - 1) xs
keepLooking = (x:) <$> replaceNTimes f n xs
If we have a "budget" of zero replacements remaining, we simply return the remainder of the list. If we have budget remaining but the list is empty, we abort, because we failed to make the expected number of replacements. Otherwise, we consult our replacement-suggester function to see which replacements are legal at the current position, and choose to either make one of them and recurse with a smaller N, or to make none and recurse with the same N.
With this tool at our disposal, the original problem is easy: we just specialize N to 1 (make exactly one replacement), and supply a replacing function that only suggests replacing -1 with 0:
replaceSingleNegativeOneWithZero :: [Int] -> [[Int]]
replaceSingleNegativeOneWithZero = replaceNTimes go 1
where go (-1) = [0]
go _ = []
And test to ensure that we get the expected output:
*Main> replaceSingleNegativeOneWithZero [-1,0,0,1,-1,-1,1,1,0]
[ [0,0,0,1,-1,-1,1,1,0]
, [-1,0,0,1,0,-1,1,1,0]
, [-1,0,0,1,-1,0,1,1,0]]
Another try:
zeros :: [Int] -> [Int] -> [[Int]]
zeros _ [] = []
zeros h (x:xs) = [h ++ newX:xs] ++ zeros nextH xs
where newX = if x == (-1) then 0 else x
nextH = h ++ [x]
switch xs = ((filter (/= xs)) . (zeros [])) xs
Usage:
main = print $ switch [-1, 0, 0, 1, -1, -1, 1, 1, 0]
I am having trouble finding the correct syntax for manipulating a list of lists.
Here's what I have
> sumLsts :: [[a]] -> [[a]] -> [[a]]
> sumLsts [[]] [[]] = [[]]
> sumLsts [(x:xs):tx] [(y:ys):ty] = [((+) x y) : sumLsts xs ys] : sumLsts tx ty
Here's sample input and output
> sumLsts [[1,1,1], [1,10,20], [-3, -4, -2]] [[3,5,6],[2,3,4],[2,3,2]]
> [[4,6,7],[3,13,24],[-1,-1,0]]
I was thinking that [(x:xs):tx] would have (x:xs) be seen as a single list and tx be seen as the following list. Haskell doesn't seem to agree.
Here is the error message
Couldn't match expected type 'a' with actual type '[[a0]]'
'a' is a rigid type variable bound by
the type signature for:
sumLsts :: forall a. [[a]] -> [[a]] -> [[a]]
In the pattern: x : xs
In the pattern: (x : xs) : tx
In the pattern [(x : xs) : tx]
Relevant bindings include
sumLsts :: [[a]] -> [[a]] -> [[a]]
As is pointed out in the comments on the question, (x:xs) is the pattern for an object of type [a], whether the a there is Int, String, Bool, or even [a] itself like [Int].
In this case your pattern match should be:
sumLsts ((x:xs):tx) ((y:ys):ty) = ...
{- to [[1, 3, 6], [2, 4, 7], [3, 5, 8]], ((x:xs): tx) matches:
x = 1
xs = [3, 6]
tx = [[2, 4, 7], [3, 5, 8]]
-}
However do note that your function is just:
sumLsts = zipWith (zipWith (+))
zipWith pairs two lists together with a joining function, such that
zipWith f [x1, x2, ..., xn] [y1, y2, ..., yn] =
[ f x1 y1
, f x2 y2
, ...
, f xn yn ]
In this case, your outer two lists get paired together so each sublist is an x and y. You're trying to pair those together with addition, so f is another zipWith, this time zipWith (+)
zipWith (zipWith (+)) [[1,1,1], [1,10,20], [-3, -4, -2]] [[3,5,6],[2,3,4],[2,3,2]]
= [ [ 1, 1, 1] `zipWith (+)` [3, 5, 6]
, [ 1, 10, 20] `zipWith (+)` [2, 3, 4]
, [-3, -4, -2] `zipWith (+)` [2, 3, 2]]
= [ [ 1 + 3
, 1 + 5
, 1 + 6]
, [ 1 + 2
, 10 + 3
, 20 + 4]
, [ -3 + 2
, -4 + 3
, -2 + 2] ]
How do you find nth elements in the matrix at a given row and column position? For example, if you have
type Matrice a = [[a]]
example :: Matrice Int
example = [ [3, 5],
[2, 1],
[0, 4],
[6, 8] ]
Prelude > example 0 1
5
Prelude > example 2 0
0
Prelude > example 1 1
2
I know how to work out with only given list such as
nth :: Int -> [a] -> Maybe a
nth _ [] = Nothing
nth 1 (x : _) = Just x
nth n (_ : xs) = nth (n - 1) xs
But my question is, how do you access nth element in a matrix as in the given example
Just handle each list individually, and !! will work:
Prelude> example
[[3,5],[2,1],[0,4],[6,8]]
Prelude> :t example
example :: Matrice Int
Prelude> example !! 0 !! 1
5
But lists are probably not the right data structure for this, because indexing is O(n). Depending on your task, Data.Vector or Data.Array may be better suited. See also Haskell: Lists, Arrays, Vectors, Sequences.
!! can be used for accessing an element by index, but be careful, since it's raising an exception, if the index is too large.
example !! 2 !! 0
And you've already written a function for accessing nth element of a list, just apply it twice:
nth :: Int -> Int -> [[a]] -> Maybe a
nth k n matrix = nth' n =<< nth' k matrix
where
nth' _ [] = Nothing
nth' 0 (x: _) = Just x
nth' n (_ : xs) = nth' (n - 1) xs
Or using your created Matrice type:
nth :: Matrice a -> Int -> Int -> Maybe a
nth matrix k n = nth' n =<< nth' k matrix
where
nth' _ [] = Nothing
nth' 0 (x: _) = Just x
nth' n (_ : xs) = nth' (n - 1) xs
SML length function:
fun length(L) =
if (L=nil) then 0
else 1+length(tl(L));
For example:
length [1,2,3] = 3;
length [ [5], [4], [3], [2,1] ] = 4;
Based on the code, how do I change it if I also want to count the elements in the list of the list?
For example:
length [ [5], [4], [3], [2,1] ] = 5;
You could create another function that will use your function as follows:
fun d_length ( [] ) = 0
| d_length ( l :: l' ) = length(l) + d_length(l');
d_length[ [5], [4], [3], [2,1] ];
Or alternatively, use the build in reducer:
List.foldl (fn(e,a) => length(e) + a) 0 [ [5], [4], [3], [2,1] ];
You don't want to make the comparison L=nil as this only works for lists of types that are comparable (e.g. not lists of functions). Rather, you want the pattern matching that Kevin Johnson suggests;
fun length [] = 0
| length (x::xs) = 1 + length xs
Or using tail-recursion:
fun length xs =
let fun len [] n = n
| len (x::xs) n = len xs (1+n)
in len xs 0 end
Unlike length : 'a list -> int, this function has type 'a list list -> int.
The combined length of all sublists can be achieved in a number of ways. E.g.
fun length2 xss = List.foldl op+ 0 (List.concat xss)
But as Kevin's answer also takes advantage of, there really isn't any point in building a new list with List.concat xss when all we do is destroy it again moments later. So to shamelessly rip his solution:
fun length2 xss = List.foldl (fn (xs, sum) => length xs + sum) 0 xss
which is probably the most readable way to express that function, too, but if you were to try to code golf that function really short, you could also rewrite the inner closure using higher-order functions:
fun curry f x y = f (x, y)
fun uncurry f (x, y) = f x y
fun length2 xss = List.foldl (uncurry (curry op+ o length)) 0 xss
Here is a pattern-matching straight recursion version which doesn't use the built-in length function but instead computes the total length ("tol") directly:
fun tol [] = 0
| tol ([]::xss) = tol xss
| tol ((x::xs)::xss) = 1 + tol (xs::xss);
The order of parenthesis in the final clause is important. It overrides the right-associativity of :: so that the x in (x::xs)::xss is interpreted as the head of the first list in xss rather than head of xss itself.
The pattern of these answers seems to be to close with a fold, and I don't want to break pattern. Here is a fold which folds into a sum a list obtained by mapping length over a list of lists:
fun tol xss = foldl op+ 0 (map length xss);