Rotate a matrix in Haskell - haskell

I have this type Mat a = [[a]] to represent a matrix in haskell.
I have to write a function which rotate a matrix, for e.g [[1,2,3],[0,4,5],[0,0,6]] will become [[3,5,6],[2,4,0],[1,0,0]] so I made this:
rotateLeft :: Mat a->Mat a
rotateLeft [[]] = []
rotateLeft (h:t) = (map last (h:t)):(rotateLeft (map init (h:t)))
but the output is
[[3,5,6],[2,4,0],[1,0,0],[*** Exception: Prelude.last: empty list
I don't know what to put in the base case to avoid this exception.
Apreciate any help.

I'm an old man in a hurry. I'd do it like this (importing Data.List)
rotl :: [[x]] -> [[x]]
rotl = transpose . map reverse

I think the simplest solution would be:
import Data.List
rotateLeft :: [[a]] -> [[a]]
rotateLeft = reverse . transpose
rotateRight :: [[a]] -> [[a]]
rotateRight = transpose . reverse
Data.List is a standard module.
transpose slices rows into columns, which is almost like rotating, but leaves the columns in the wrong order, so we just reverse them.

Your list won't be empty but a list of empty lists, you can do the following to pattern match based on the first sublist (assuming Mat ensures data structure consistency)
rl [] = []
rl ([]:_) = []
rl m = map last m : (rl (map init m))
rl mat
[[3,5,6],[2,4,0],[1,0,0]]
You're missing the second case.

The problem is that your pattern isn't matching. Stepping through what your code does, we start with:
Prelude> let x = [[1,2,3],[0,4,5],[0,0,6]]
Prelude> :m +Data.List
Prelude Data.List> map last x
[3,5,6]
Prelude Data.List> let y = map init x
Prelude Data.List> y
[[1,2],[0,4],[0,0]]
Prelude Data.List> map last y
[2,4,0]
Prelude Data.List> let z = map init y
Prelude Data.List> z
[[1],[0],[0]]
Prelude Data.List> map last z
[1,0,0]
Prelude Data.List> map init z
[[],[],[]]
So the basic problem is that your base case you're matching on is not [[],[],[]] but is instead [[]], so that pattern doesn't match.
You now have more or less three options: you can (a) try to terminate when the first empty list is seen; this is written in Haskell as any null, using the any function and the null function, both defined in the Prelude; or (b) you can hardcode that this only works for 3x3 matrices, and just match against [[],[],[]], or (c) you can try to terminate when all lists are empty (all null), in which case you can either skip elements that don't exist or wrap everything in the Maybe x datatype, so that missing elements are represented by Nothing while present elements are represented by Just x.

rotateLeft [] = []
rotateLeft ([]:_) = []
rotateLeft (h:t) = (map last (h:t)):(rotateLeft (map init (h:t)))
The first pattern is for the case when the head of the list of lists is longer than other elements.
You got the second pattern wrong: if we have a proper matrix (ie elements are of the same length), then the base case is a list of empty lists. However, you wrote [[]], which is only true if the initial list consists of a single list.

Related

Avoiding double traversal in outputting a L-shaped matrix [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
Improve this question
I am trying to traverse a list of Lists in L Shape. For example: lShapedTraverse [[1,2,3],[4,5,6],[7,8,9]] will result in [[1,2,3,6,9],[4,5,8],[7]]
I have the following algorithm which gives the desired output:
lShapedTraverse :: [[a]] -> [[a]]
lShapedTraverse [] = []
lShapedTraverse [xs] = [xs]
lShapedTraverse (xs:xss) = let (rest, col) = ((map init xss), (map last xss))
in (xs ++ col) : lShapedTraverse rest
This is traversing the list of list 2 times to get init and last, which I think can be avoided using a custom function that can do initAndLast in one traversal.
I am trying to see if I can do a more efficient implementation and idiomatic Haskell.
We could write initAndLast, but it wouldn't help performance very
much because that would still be a lot of work to do for each element
of the result.
We really want to be working at the beginning of the lists so we can
get at the elements with only a constant amount of work. We can
arrange this by flipping the matrix left-to-right with map reverse.
Now we always work with the first row and column. We just have to
remember to un-reverse the row parts as we produce them.
-- L shapes from top left to top right then down to bottom right
lShaped :: [[a]] -> [[a]]
lShaped = lShaped' . map reverse
-- L shapes from top right backwards to top left then down to bottom left
lShaped' :: [[a]] -> [[a]]
lShaped' [] = []
lShaped' ([]:_) = []
lShaped' (xs:xss) = (reverse xs ++ map head xss) : lShaped' (map tail xss)
We need the two base cases to deal with rectangles taller than they are
wide as well as wider than they are tall - your code is missing one
of these.
Alternatively we could try to use library functions rather than doing
manual recursion.
This function slices a rectangle into two parts along an upward-sloping line. n is
the length of the first row of the upper/left part, or if n is greater
than the width of the rectangle you have to imagine it as a coordinate
outside the rectangle defining the top-right point of the cutting
line, so that some full rows will appear in the upper/left part before
we get down to the cut.
slice :: Int -> [[a]] -> ([[a]], [[a]])
slice n xss = unzip (zipWith splitAt [n,n-1 ..] xss)
Using slice splits up the elements nicely for the horizontal and
vertical parts of the Ls, but the vertical parts aren't arranged in a
useful way. Rather than try to rearrange them we can use slice again
on the transpose of the matrix to get them in the right lists.
Finally we put the horizontal and vertical parts together with
zipWith (++).
lShaped'' :: [[a]] -> [[a]]
lShaped'' [] = []
lShaped'' xss = zipWith (++) rowParts (reverse colParts)
where
(rowParts, _) = slice width xss
(_, colParts) = slice width (transpose xss)
width = length (head xss)
I don't know if I like this solution better than the manual recursion
but there it is. It's always a bit of a shame to introduce lengths
and numbers into a list algorithm but I don't see a cleaner way at the
moment.
As there are several possibilities to represent the input matrix, we can try to separate the “navigation”, i.e. choice of elements, from the actual matrix representation.
In order to achieve this, we can easily write a recursive function that produces the 2D list of Cartesian coordinates to be extracted from the input matrix:
{-# LANGUAGE TupleSections #-}
-- returns 2D list of Cartesian coordinates for entries of L-shaped matrix:
coordList :: Int -> [[(Int,Int)]]
coordList n = go n 0 n where -- rl: Row Length sr: Starting Row
go n sr rl = ((map (sr,) [0..(rl-1)]) ++ (map (,rl-1) [(sr+1)..(n-1)]) ) :
if (rl > 1) then go n (sr+1) (rl-1) else []
Checking under the ghci interpreter:
λ>
λ> coordList 3
[[(0,0),(0,1),(0,2),(1,2),(2,2)],[(1,0),(1,1),(2,1)],[(2,0)]]
λ>
Next, we test our new coordList function by naïvely using the inefficient !! list extraction operator:
λ> printAsLines xs = mapM_ (putStrLn . show) xs
λ>
λ> xss = [[1,2,3], [4,5,6], [7,8,9]]
λ>
λ> printAsLines $ map (map (\(i,j) -> ((xss !! i) !! j))) $ (coordList 3)
[1,2,3,6,9]
[4,5,8]
[7]
λ>
This might be inefficient, but it is correct. And so we can have a more efficient version of this by replacing lists by vectors and the list !! operator by the equivalent vector ! operator:
import qualified Data.Vector as V
-- vector-based version:
lShapedTraverse :: [[a]] -> [[a]]
lShapedTraverse xss =
let
rank = length (head xss) -- matrix rank
pairs = coordList rank -- 2D list of Cartesian coordinates
matrix = V.fromList (map V.fromList xss) -- 2D vector
in
map (map (\(i,j) -> ((matrix V.! i) V.! j))) $ pairs
Test program:
printAsLines :: Show α => [α] -> IO ()
printAsLines xs = mapM_ (putStrLn . show) xs
main :: IO ()
main = do
let xss = [[1,2,3], [4,5,6], [7,8,9]]
lMat1 = lShapedTraverse xss
putStrLn $ "res1 = "
printAsLines lMat1
Program output:
res1 =
[1,2,3,6,9]
[4,5,8]
[7]

Splitting lists in Haskell

In Haskell I need to perform a function, whose declaration of types is as follows:
split ::[Integer] -> Maybe ([Integer],[Integer])
Let it work as follows:
split [1,2,3,4,5,15] = Just ([1,2,3,4,5],[15])
Because, 1 + 2 + 3 + 4 + 5 = 15
split [1,3,3,4,3] = Just ([1,3,3],[4,3])
Because, 1 + 3 + 3 = 7 = 4 + 3
split [1,5,7,8,0] = Nothing
I have tried this, but it doesn't work:
split :: [Integer] -> ([Integer], [Integer])
split xs = (ys, zs)
where
ys <- subsequences xs, ys isInfixOf xs, sum ys == sum zs
zs == xs \\ ys
Determines whether the list of positive integers xs can be divided into two parts (without rearranging its elements) with the same sum. If possible, its value is the pair formed by the two parts. If it's not, its value is Nothing.
How can I do it?
Not a complete answer, since this is a learning exercise and you want hints, but if you want to use subsequences from Data.List, you could then remove each element of the subsequence you are checking from the original list with \\, to get the difference, and compare the sums. You were on the right track, but you need to either find the first subsequence that works and return Just (ys, zs), or else Nothing.
You can make the test for some given subsequence a predicate and search with find.
What you could also do is create a function that gives all possible splittings of a list:
splits :: [a] -> [([a], [a])]
splits xs = zipWith splitAt [1..(length xs)-1] $ repeat xs
Which works as follows:
*Main> splits [1,2,3,4,5,15]
[([1],[2,3,4,5,15]),([1,2],[3,4,5,15]),([1,2,3],[4,5,15]),([1,2,3,4],[5,15]),([1,2,3,4,5],[15])]
Then you could just use find from Data.List to find the first pair of splitted lists that have equal sums:
import Data.List
splitSum :: [Integer] -> Maybe ([Integer], [Integer])
splitSum xs = find (\(x, y) -> sum x == sum y) $ splits xs
Which works as intended:
*Main> splitSum [1,2,3,4,5,15]
Just ([1,2,3,4,5],[15])
Since find returns Maybe a, the types automatically match up.

Generating all combinations of 6 Xs with 3 Qs in Haskell

I am trying to generate a list of all strings that consist of 6 Xs and 3 Qs.
A subset of the list I am trying to generate is as follows:
["XXXXXXQQQ", "XQXXQXXQX", "QXQXQXXXX",...
What is a good way to go about this?
Here is a dynamic programming solution using Data.Array. mem just stores memoized values.
import Data.Array
strings :: Int -> Int -> [String]
strings n m = strings' n m
where
mem :: Array (Int,Int) [String]
mem = array ((0,0),(n,m)) [ ((i,j), strings' i j) | i <- [0..n], j <- [0..m] ]
strings' 0 m = [replicate m 'X']
strings' n 0 = [replicate n 'Q']
strings' n m = (('Q':) <$> mem ! (n-1,m)) ++ (('X':) <$> mem ! (n,m-1))
The naive solution is to recursively choose one of X or Q until we run out of choices to make. This is especially convenient when using the list monad to model the nondeterministic choice, and leads to quite short code:
stringsNondet m 0 = [replicate m 'X']
stringsNondet 0 n = [replicate n 'Q']
stringsNondet m n = do
(char, m', n') <- [('X', m-1, n), ('Q', m, n-1)]
rest <- stringsNondet m' n'
return (char:rest)
The disadvantage of this approach is that it does a lot of extra work. If we choose an X and then choose a Q, the continuations are the same as if we had chosen a Q and then an X, but these continuations will be recomputed in the above. (And similarly for other choice paths that lead to shared continuations.)
Alec has posted a dynamic programming solution which solves this problem by introducing a recursively-defined array to share the subcomputations. I like this solution, but the recursive definition is a bit mind-bending. The following solution is also a dynamic programming solution -- subcomputations are also shared -- but uses no hand-written recursion. It does make use of standard recursive patterns (map, zip, iterate, ++, and !!) but notably does not require "tying the knot" as Alec's solution does.
As a warmup, let's discuss the type of the function of interest to us:
step :: [[String]] -> [[String]]
The final result of interest to us is [String], a collection of strings with a fixed number m of 'X's and a fixed number n of 'Q's. The step function will expect a collection of results, all of the same length, and will assume that the result at index m has m copies of 'X'. It will also produce a result with these properties, and where each result is one longer than the input results.
We implement step by producing two intermediate [[String]]s, one with an extra 'X' compared to the input results and one with an extra 'Q'. These two intermediates can then be zipped together with a little "stutter" to represent the slight difference in 'X' count between them. Thus:
step css = zipWith (++)
([[]] ++ map (map ('X':)) css)
(map (map ('Q':)) css ++ [[]])
The top-level function is now easy to write: we simply index into the iterated version of step by the length of the final string we want, then index into the list of results we get that way by the number of 'X's we want.
strings m n = iterate step [[[]]] !! (m+n) !! m
A bonus of this approach is the single, aesthetically pleasing base case of [[[]]].
Use permutations and nub functions from Data.List:
Prelude Data.List> nub $ permutations "XXXXXXQQQ"
["XXXXXXQQQ","QXXXXXXQQ","XQXXXXXQQ","XXQXXXXQQ","XXXQXXXQQ","XXXXQXXQQ","XXXXXQXQQ","QQXXXXXXQ","QXQXXXXXQ","QXXQXXXXQ","QXXXQXXXQ","QXXXXQXXQ","QXXXXXQXQ","XQQXXXXXQ","XQXQXXXXQ","XQXXQXXXQ","XQXXXQXXQ","XQXXXXQXQ","XXQQXXXXQ","XXQXQXXXQ","XXQXXQXXQ","XXQXXXQXQ","XXXQQXXXQ","XXXQXQXXQ","XXXQXXQXQ","XXXXQQXXQ","XXXXQXQXQ","XXXXXQQXQ","QQQXXXXXX","QQXQXXXXX","QQXXQXXXX","QQXXXQXXX","QQXXXXQXX","QQXXXXXQX","QXQQXXXXX","XQQQXXXXX","XQQXQXXXX","XQQXXQXXX","XQQXXXQXX","XQQXXXXQX","QXQXQXXXX","QXQXXQXXX","QXQXXXQXX","QXQXXXXQX","QXXQQXXXX","XQXQQXXXX","XXQQQXXXX","XXQQXQXXX","XXQQXXQXX","XXQQXXXQX","XQXQXQXXX","XQXQXXQXX","XQXQXXXQX","QXXQXQXXX","QXXQXXQXX","QXXQXXXQX","QXXXQQXXX","XQXXQQXXX","XXQXQQXXX","XXXQQQXXX","XXXQQXQXX","XXXQQXXQX","XXQXQXQXX","XXQXQXXQX","XQXXQXQXX","XQXXQXXQX","QXXXQXQXX","QXXXQXXQX","QXXXXQQXX","XQXXXQQXX","XXQXXQQXX","XXXQXQQXX","XXXXQQQXX","XXXXQQXQX","XXXQXQXQX","XQXXXQXQX","QXXXXQXQX","XXQXXQXQX","QXXXXXQQX","XQXXXXQQX","XXQXXXQQX","XXXQXXQQX","XXXXQXQQX","XXXXXQQQX"]
We can have a faster implementation as well:
insertAtEvery x [] = [[x]]
insertAtEvery x (y:ys) = (x:y:ys) : map (y:) (insertAtEvery x ys)
combinations [] = [[]]
combinations (x:xs) = nub . concatMap (insertAtEvery x) . combinations $ xs
Comparison with the previous solution in ghci:
Prelude Data.List> (sort . nub . permutations $ "XXXXXXQQQ") == (sort . combinations $ "XXXXXXQQQ")
True
Prelude Data.List> :set +s
Prelude Data.List> combinations "XXXXXXQQQ"
["XXXXXXQQQ","XXXXXQXQQ","XXXXXQQXQ","XXXXXQQQX","XXXXQXXQQ","XXXXQXQXQ","XXXXQXQQX","XXXXQQXXQ","XXXXQQXQX","XXXXQQQXX","XXXQXXXQQ","XXXQXXQXQ","XXXQXXQQX","XXXQXQXXQ","XXXQXQXQX","XXXQXQQXX","XXXQQXXXQ","XXXQQXXQX","XXXQQXQXX","XXXQQQXXX","XXQXXXXQQ","XXQXXXQXQ","XXQXXXQQX","XXQXXQXXQ","XXQXXQXQX","XXQXXQQXX","XXQXQXXXQ","XXQXQXXQX","XXQXQXQXX","XXQXQQXXX","XXQQXXXXQ","XXQQXXXQX","XXQQXXQXX","XXQQXQXXX","XXQQQXXXX","XQXXXXXQQ","XQXXXXQXQ","XQXXXXQQX","XQXXXQXXQ","XQXXXQXQX","XQXXXQQXX","XQXXQXXXQ","XQXXQXXQX","XQXXQXQXX","XQXXQQXXX","XQXQXXXXQ","XQXQXXXQX","XQXQXXQXX","XQXQXQXXX","XQXQQXXXX","XQQXXXXXQ","XQQXXXXQX","XQQXXXQXX","XQQXXQXXX","XQQXQXXXX","XQQQXXXXX","QXXXXXXQQ","QXXXXXQXQ","QXXXXXQQX","QXXXXQXXQ","QXXXXQXQX","QXXXXQQXX","QXXXQXXXQ","QXXXQXXQX","QXXXQXQXX","QXXXQQXXX","QXXQXXXXQ","QXXQXXXQX","QXXQXXQXX","QXXQXQXXX","QXXQQXXXX","QXQXXXXXQ","QXQXXXXQX","QXQXXXQXX","QXQXXQXXX","QXQXQXXXX","QXQQXXXXX","QQXXXXXXQ","QQXXXXXQX","QQXXXXQXX","QQXXXQXXX","QQXXQXXXX","QQXQXXXXX","QQQXXXXXX"]
(0.01 secs, 3,135,792 bytes)
Prelude Data.List> nub $ permutations "XXXXXXQQQ"
["XXXXXXQQQ","QXXXXXXQQ","XQXXXXXQQ","XXQXXXXQQ","XXXQXXXQQ","XXXXQXXQQ","XXXXXQXQQ","QQXXXXXXQ","QXQXXXXXQ","QXXQXXXXQ","QXXXQXXXQ","QXXXXQXXQ","QXXXXXQXQ","XQQXXXXXQ","XQXQXXXXQ","XQXXQXXXQ","XQXXXQXXQ","XQXXXXQXQ","XXQQXXXXQ","XXQXQXXXQ","XXQXXQXXQ","XXQXXXQXQ","XXXQQXXXQ","XXXQXQXXQ","XXXQXXQXQ","XXXXQQXXQ","XXXXQXQXQ","XXXXXQQXQ","QQQXXXXXX","QQXQXXXXX","QQXXQXXXX","QQXXXQXXX","QQXXXXQXX","QQXXXXXQX","QXQQXXXXX","XQQQXXXXX","XQQXQXXXX","XQQXXQXXX","XQQXXXQXX","XQQXXXXQX","QXQXQXXXX","QXQXXQXXX","QXQXXXQXX","QXQXXXXQX","QXXQQXXXX","XQXQQXXXX","XXQQQXXXX","XXQQXQXXX","XXQQXXQXX","XXQQXXXQX","XQXQXQXXX","XQXQXXQXX","XQXQXXXQX","QXXQXQXXX","QXXQXXQXX","QXXQXXXQX","QXXXQQXXX","XQXXQQXXX","XXQXQQXXX","XXXQQQXXX","XXXQQXQXX","XXXQQXXQX","XXQXQXQXX","XXQXQXXQX","XQXXQXQXX","XQXXQXXQX","QXXXQXQXX","QXXXQXXQX","QXXXXQQXX","XQXXXQQXX","XXQXXQQXX","XXXQXQQXX","XXXXQQQXX","XXXXQQXQX","XXXQXQXQX","XQXXXQXQX","QXXXXQXQX","XXQXXQXQX","QXXXXXQQX","XQXXXXQQX","XXQXXXQQX","XXXQXXQQX","XXXXQXQQX","XXXXXQQQX"]
(0.71 secs, 161,726,128 bytes)

Is `group list by size` a fold?

I came across this problem : grouping the elements of a list by packet of the same size, so that
> groupBy 3 [1..10]
[[1,2,3], [4,5,6], [7,8,9], [10]]
Nothing really hard to do, but first I was surprise that I couldn't find a function for it.
My first try was
groupBy _ [] = []
groupBy n xs = g : groupBy n gs
where (g, gs) = splitAt n xs
So far so good, it works, even on infinite list. However I don't like the first line groupBy _ [] = []. Seems a good candidate for a fold but I couldn't figure it out.
So can this function can be written as a fold or as a one liner ?
Update
My attempt at a one liner:
groupBy' n l = map (map snd) $ groupBy ((==) `on` fst) $ concatMap (replicate n) [1..] `zip` l
It took me 10 times more to write that the initial attempt.
Update 2
Following Ganesh answer and using unfoldr and the help of pointfree I came out with this convoluted point free solution
groupBy' n = unfoldr $ listToMaybe . (ap (>>) (return.splitAt n))
You can do it as a fold with some gymnastics, but it's much nicer as an unfold:
unfoldr (\xs -> if null xs then Nothing else Just (splitAt n xs))
[You'll need to import Data.List if you haven't already]
The type of unfoldr is:
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
The idea of unfoldr is that a generating function decides whether to stop (Nothing) or keep going (Just). If the result is Just then the first element of the tuple is the next element of the output list, and the second element is passed to the generating function again.
As #leftroundabout pointed out in a comment on the question, an unfold is much more natural here because it treats the output list elements as similar to each other, whereas in a fold the input list elements should be treated similarly. In this case the need to start a new sublist every n elements of the input list makes this harder.

Subdividing a list in haskell

How can I group a list into smaller lists of equal length (except last sublist) in haskell?
E.g.
sublist 3 [1,2,3,4,5,6,7,8] -> [[1,2,3],[4,5,6],[7,8]]
sublist 2 [4,1,6,1,7,3,5,3] -> [[4,1],[6,1],[7,3],[5,3]]
Try:
import Data.List.Split
> splitEvery 2 [4,1,6,1,7,3,5,3]
[[4,1],[6,1],[7,3],[5,3]]
If you want to stick to prelude, you can pull this off using splitAt.
splitEvery _ [] = []
splitEvery n list = first : (splitEvery n rest)
where
(first,rest) = splitAt n list
The Data.List.Split module has a chunksOf function for this:
Prelude> import Data.List.Split
Prelude Data.List.Split> chunksOf 3 [1,2,3,4,5,6,7,8,9,10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
Prelude Data.List.Split> chunksOf 3 []
[]
It seemed to be installed by default on my machine, but you might need to get it with cabal.
Another solution that I like is:
splitEvery :: Int -> [a] -> [[a]]
splitEvery n = takeWhile (not.null) . map (take n) . iterate (drop n)
Yet another solution:
split :: Int -> [a] -> [[a]]
split n = unfoldr (\s -> if null s then Nothing else Just $ splitAt n s)
I know this is old, but since this seems to be a post for people who are fairly new to Haskell, I felt like posting my solution too. I tried to solve this problem by using Prelude, only:
sublist :: Int -> [a] -> [[a]]
sublist n ls
| n <= 0 || null ls = []
| otherwise = take n ls:sublist n (drop n ls)
Testing
sublist 3 [1,2,3,4,5,6] -- λ> [[1,2,3], [4,5,6]]
sublist 5 [1,2,3] -- λ> [[1,2,3]]
sublist (-1) [1,2,3] -- λ> []
sublist 20 [] -- λ> []
This list comprehension uses tails. Since the first set starts with one, all subsequent subsets start with an odd number.
ts n ls = [take n l|l<-init$tails ls,odd (head l)]
n is the size-of-sublist, ls is the source list.
The next one will take any list and include unmatched elements. It is set up to do pairs only. It is obvious how to parameterize it to do any chunk size.
np ls = [take 2 (drop a ls)|a<-[0,2..(length ls)-1]]
Just include an n as a parameter and replace the 2's in the formula, one after take and one after 0 in the generator.

Resources