1

I need to construct an auxiliar function in Haskell that, for example: let's A be a matrix such as:

[[10,2, 3, 4]
,[5, 10,10,8]
,[9, 10,10,12]
,[10,14,15,16]] 

returns me a boolean if there is, at least, a triple followed tens list that are diagonal, thus:

*Main> [[10,2,3,4],[5,10,10,8],[9,10,10,12],[10,14,15,16]] 

result: True

because in the matrix above we have three 10's in main diagonal and three 10's in the other diagonal (in this case, both diagonals are main and secondary, respectively. But it doesn't have to be like that ) This code calculates the main diagonal of a matrix:

diagonal :: [[Int]] -> [Int]
diagonal [] = []
diagonal (x:xs) = head x : diagonal (map tail xs)

but i need to solve it for any diagonal and no necessarily for square matrix.

I also made a function to group 3 by 3, but i don't know how to "connect" with the previous idea:

group3in3:: Int -> [a] -> [[a]]
group3in3 _ [] = [[]]
group3in3n n xs
  |n > 0 = (take n xs) : (group3in3  n (drop n xs))
  |otherwise = error "Error" 

I don't have a lot of experience with Haskell. Any help would be appreciated.

dfeuer
  • 48,079
  • 5
  • 63
  • 167
vbcod
  • 23
  • 3
  • 1
    My answer [here](https://stackoverflow.com/a/46900780/791604) describes in detail how to construct a function that returns the diagonals that go down and to the left for a matrix. The diagonals that go down and to the right of a matrix are the same as the diagonals that go down and to the left in its horizontally (or vertically) flipped form. – Daniel Wagner Jan 01 '21 at 00:03
  • 2
    ...but also this sounds a lot like a homework problem, and you will be cheating yourself out of an excellent learning experience if you just take my code and run with it. Perhaps a reasonable middle ground would be to read the English text of my answer and skip reading the code, then try to write the code yourself that implements the ideas in the text. – Daniel Wagner Jan 01 '21 at 00:03

1 Answers1

0

Here are some hints. Suppose you wrote a function to check if there was a main diagonal of three 10s in the top-level corner:

cornertens :: [[Int]] -> Bool

This would give True for the following matrix, only checking for 10s in this exact position:

[[10, 0, 0, 0]
,[ 0,10, 0, 0]
,[ 0, 0,10, 0]
,[ 0, 0, 0, 0]]

Now, you could write a recursive function looking for this pattern not just in the top-left corner, but starting anywhere along the top row:

toptens :: [[Int]] -> Bool
toptens mtx = cornertens mtx || toptens (map tail mtx)

This definition won't quite work. It's a recursive function with no base case, so it's an infinite loop if the 10s aren't found, but you should be able to modify it slightly so it knows when to stop recursing. Once it's working, it should be able to find these 10s:

[[0, 10, 0, 0, 0]
,[0,  0,10, 0, 0]
,[0,  0, 0,10, 0]
,[0,  0, 0, 0, 0]]

but also not hang if the matrix is all-zeros.

Once you've got that, you should be able to write a recursive function that looks for this pattern not just anywhere along the top row, but starting in any row:

righthandtens :: [[Int]] -> Bool
righthandtens mtx = toptens mtx || righthandtens (tail mtx)

I've called tens in this orientation from top left to bottom right "right hand". Again, this needs to be modified to know when to stop, but once it's working, it'll find these 10s:

[[0,  0, 0, 0, 0]
,[0, 10, 0, 0, 0]
,[0,  0,10, 0, 0]
,[0,  0, 0,10, 0]

and any other 10s in this particular orientation. If you have a matrix with 10s in the other orientation:

[[0,  0, 10, 0]
,[0, 10,  0, 0]
,[10, 0,  0, 0]]

you can reverse its rows:

[[10, 0,  0, 0]
,[0, 10,  0, 0]
,[0,  0, 10, 0]]

to change the orientation letting you find it with righthandtens. This lets you define:

anytens mtx = righthandtens mtx || righthandtens (reverse mtx)

which should be able to find those 10s in any diagonal anywhere.

K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71