0

The objective of the function is to take a board in the form of a list of lists of Squares 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]].

  • 1
    I recommend starting with [a tutorial](https://wiki.haskell.org/Tutorials). Once you have enough knowledge to try, do; when you get to a point where you feel you cannot make progress, then you will have a question we'll be excited about answering. Show us the code you've arrived at and tell us why you think it's not possible to fix whatever problem it has, and we'll help you over that bump. (Right now the way to make progress is obvious -- educate yourself -- so there's nothing for us to help you with.) – Daniel Wagner Apr 21 '22 at 16:42
  • 1
    StackOverflow is *not* a homework service. Make a fair attempt and come back with *specific* questions about that attempt. See the [*open letter to students with homework problems*](https://softwareengineering.meta.stackexchange.com/questions/6166/open-letter-to-students-with-homework-problems). – Willem Van Onsem Apr 21 '22 at 17:54
  • 1
    Hey guys I made a lot of progress. Is there anyone actually still interested in giving me a hand? – Emanuele Filiberto Apr 22 '22 at 14:31
  • @DanielWagner Would you please help reopening the question? – Emanuele Filiberto Apr 22 '22 at 15:20
  • @WillemVanOnsem Would you please help reopening the question? – Emanuele Filiberto Apr 22 '22 at 15:20
  • related: [Testing diagonally adjacent elements in nested lists](https://stackoverflow.com/questions/60798643/testing-diagonally-adjacent-elements-in-nested-lists) – Will Ness Apr 22 '22 at 15:39
  • For transforming one `Bool` to another, [Hoogle's got your back.](https://hoogle.haskell.org/?hoogle=Bool%20-%3E%20Bool) – Daniel Wagner Apr 22 '22 at 15:41
  • @DanielWagner I tried that already but wherever I put not in the code, it isn't working. – Emanuele Filiberto Apr 22 '22 at 16:46
  • @WillNess Greetings to the original poster! I actually learnt from the highest score answer to write this, but while his code is simple and elegant it actually has the same problem: the boolean returned is always the opposite of what the question wants, and wherever I tried adding 'not' in the code, it isn't working. – Emanuele Filiberto Apr 22 '22 at 16:49
  • I've shown my attempts to solve the problem in Update No.2. Please check it out. – Emanuele Filiberto Apr 22 '22 at 17:35
  • I just posted someone else's question there. :) will look into yours when I have some time; meantime I've voted to reopen this one... – Will Ness Apr 22 '22 at 18:21
  • naming is important. `diagchecker = noGreenUnderWhiteDiagonally ; noGreenUnderWhiteDiagonally rows = null [ () | (a:b:_) <- tails rows, greenUnderWhite a (drop 1 b) || greenUnderWhite (drop 1 a) b] ; greenUnderWhite a b = or $ zipWith (...) a b`. – Will Ness Apr 22 '22 at 19:08
  • @WillNess So you are not using the 'anyDiags' predicate here anymore? And since now the question is reopened, would you mind writing this into an answer? – Emanuele Filiberto Apr 23 '22 at 03:11

1 Answers1

1

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.

Will Ness
  • 70,110
  • 9
  • 98
  • 181