The objective of the function is to take a board in the form of a list of lists of Square
s and returns True
if no Square
contains a white where there is a green square diagonally adjacent to it in the following row.
The function signature is:
diagchecker :: [[Square]] -> Bool
Square is defined as:
data Square = White | Green | Empty deriving Eq
For example, diagchecker [[White,Empty],[Empty,Green]]
should return False
.
diagchecker [[Green,Empty],[Empty,White]]
should return True
.
diagchecker [[White,Green],[White,White],[Green,Empty]]
should return False
.
---------Update------------
OK I'm basically one step away from getting this right. Here is my code:
data Square = White | Green | Empty deriving Eq
diagchecker :: [[Square]] -> Bool
anyDiags :: (a -> a -> Bool) -> [[a]] -> Bool
anyDiags p = fst . foldr f (False, [])
where
f xs (a, ys) = ( a || or (zipWith p xs (drop 1 ys))
|| or (zipWith p (drop 1 xs) ys)
, xs)
greenAfterWhite x y = (x == White && y == Green)
diagchecker = anyDiags greenAfterWhite
This code actually works, and now the only problem I'm facing is that I want diagchecker
to return True
when there is no green after white, and return False
when there is green after white. Under current situation it is doing the job detecting whether there is green after white, but the result Boolean it returns is exactly the opposite of what I want. Can anyone please help me with this?
-----Update No.2-----
For changing the output I've tried changing greenAfterWhite
like this:
greenAfterWhite x y
| (x == white && y == green) = False
| otherwise = True
or this:
greenAfterWhite x y = not (x == White && y == Green)
Both of these changes all result in the diagchecker
returns TRUE
for every single input [[Square]]
.
CodePudding user response:
Since you only check the two diagonal squares below, I'll express this as a mapping on tails. You're welcome to reformulate it in terms of foldr
:
import Data.List (tails)
diagchecker = noGreenUnderWhiteDiagonally
noGreenUnderWhiteDiagonally rows =
null [ ()
| (a:b:_) <- tails rows,
greenUnderWhite a (drop 1 b)
||
greenUnderWhite (drop 1 a) b]
greenUnderWhite row1 row2 =
or $ zipWith (...) ... ...
You will need to complete the definition to check the presence of green square underneath in case the square above is white.
or
will detect whether any True
element is present in its argument list.
The negation is already built into the code, with null
detecting whether its argument list is empty. The elements of that list are not important, so we use the "bland" value, ()
.
The mapping on tails
achieves pairwise comparison of consecutive rows in your matrix.