My task is to code something that prints out this:
This is what I have done so far.
diag matrix = diag2 [] [] matrix where
diag2 [] [] [] = []
diag2 xss [] (zs:zss) = diag2 [] (reverse $ zs:xss) zss
diag2 xss ((y:ys):yss) zss = y : diag2 (ys:xss) yss zss
diag2 xss ([] :yss) zss = diag2 xss yss zss
diag2 xss [] [] = diag2 [] (reverse xss) []
Is there an easier way to code this? Also, how can I solve it if this is a very big matrix?
-
\$\begingroup\$ The problem statement is not clear. Are you trying to calculate the traversal order, or draw a picture, or what? Will you use the contents of an input matrix or just the element numbers? \$\endgroup\$Anonymous– Anonymous2016年05月28日 19:44:42 +00:00Commented May 28, 2016 at 19:44
-
\$\begingroup\$ Oh I'm sorry. It should print out: [1,2,6,3,7,11,4...] and so on. \$\endgroup\$Cyneon Bane– Cyneon Bane2016年05月29日 12:12:28 +00:00Commented May 29, 2016 at 12:12
-
\$\begingroup\$ If you just want the numbers, you can solve this without representing the matrix at all, by simple arithmetic. \$\endgroup\$Anonymous– Anonymous2016年06月25日 02:10:14 +00:00Commented Jun 25, 2016 at 2:10
2 Answers 2
One inefficiency of your solution is that is calls reverse
. This means that it will have to traverse an entire row. It also means it won't work with infinite lists.
The best implementation I've found is Data.Universe.Helpers.diagonals
from the universe-base
package.
It can even operate on an infinite list of infinite lists:
import Data.Universe.Helpers
import Control.Monad
mat = [ [i..] | i <- [1..] ]
example n = forM_ (take n $ diagonals mat) $ print
e.g.:
ghci> example 4
[1]
[2,2]
[3,3,3]
[4,4,4,4]
More info available at this SO answer: https://stackoverflow.com/a/32469565/866915
-
\$\begingroup\$ I don't want to import something. But if i use Data.Universe.Helpers hackage.haskell.org/package/universe-0.4.0.3/docs/src/… I need to import these stuffs. Sorry for the late answer. I had to do a lot of stuffs . \$\endgroup\$Cyneon Bane– Cyneon Bane2016年06月01日 13:11:53 +00:00Commented Jun 1, 2016 at 13:11
concat . concat . transpose . (zipWith (++) (iterate ([] :) [])) . map (map (: []))
seems and seams the easiest zigzag to me: this boxes all matrix elements as singleton lists to enable us to prepend increasingly many empty cells at each row head to right shift the rows diagonally, then in transposition we read out the shifted columns and unbox them pettily until you have your desired result
let fivesquare = [[e+f|e<-[1..5]]|f<-[0,5..20]]; zigzag = concat . concat . transpose . (zipWith (++) (iterate ([] :) [])) . map (map (: [])) in zigzag fivesquare
[1,2,6,3,7,11,4,8,12,16,5,9,13,17,21,10,14,18,22,15,19,23,20,24,25]
this should presumably get bulletproven for endless matrices if possible with some interspersed
... takeWhile (not . null ...