ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# fruit-in's solution

## to Queen Attack in the Haskell Track

Published at Mar 12 2021 · 1 comment
Instructions
Test suite
Solution

Given the position of two queens on a chess board, indicate whether or not they are positioned so that they can attack each other.

In the game of chess, a queen can attack pieces which are on the same row, column, or diagonal.

A chessboard can be represented by an 8 by 8 array.

So if you're told the white queen is at (2, 3) and the black queen at (5, 6), then you'd know you've got a set-up like so:

``````_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ B _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
``````

You'd also be able to answer whether the queens can attack each other. In this case, that answer would be yes, they can, because both pieces share a diagonal.

## Hints

To complete this exercise, you need to implement the following functions:

• `boardString`
• `canAttack`

You will find the type signatures already in place, but it is up to you to define the functions.

Positions are specified as two-tuples:

• The first element is the row (rank in Chess terms).
• The second element is is the column (file in Chess terms).
• (0, 0) is the top left of the board, (0, 7) is the upper right,
• (7, 0) is the bottom left, and (7, 7) is the bottom right.

## Getting Started

Please refer to the installation and learning help pages.

## Running the tests

To run the test suite, execute the following command:

``````stack test
``````

#### If you get an error message like this...

``````No .cabal file found in directory
``````

You are probably running an old stack version and need to upgrade it.

#### Otherwise, if you get an error message like this...

``````No compiler found, expected minor version match with...
Try running "stack setup" to install the correct GHC...
``````

Just do as it says and it will download and install the correct compiler version:

``````stack setup
``````

## Running GHCi

If you want to play with your solution in GHCi, just run the command:

``````stack ghci
``````

## Feedback, Issues, Pull Requests

The exercism/haskell repository on GitHub is the home for all of the Haskell exercises.

If you have feedback about an exercise, or want to help implementing a new one, head over there and create an issue. We'll do our best to help you!

## Source

J Dalbey's Programming Practice problems http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### Tests.hs

``````{-# OPTIONS_GHC -fno-warn-type-defaults #-}

import Data.Foldable     (for_)
import Test.Hspec        (Spec, describe, it, shouldBe)
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)

import Queens (boardString, canAttack)

main :: IO ()
main = hspecWith defaultConfig {configFastFail = True} specs

specs :: Spec
specs = do

-- Track-specific test cases.

describe "boardString" \$ do

it "empty board" \$ boardString Nothing Nothing
`shouldBe` unlines [ "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _" ]

it "board with just white queen" \$ boardString (Just (2, 4)) Nothing
`shouldBe` unlines [ "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ W _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _" ]

it "board with just black queen" \$ boardString Nothing (Just (0, 0))
`shouldBe` unlines [ "B _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _" ]

it "board" \$ boardString (Just (2, 4)) (Just (6, 6))
`shouldBe` unlines [ "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ W _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ _ _"
, "_ _ _ _ _ _ B _"
, "_ _ _ _ _ _ _ _" ]

-- The function described by the reference file as `create` doesn't
-- exist in this track, so only the `canAttack` test cases were
-- implemented here

describe "canAttack" \$ do

let test (description, white, black, expected) =
it description \$ canAttack white black `shouldBe` expected

cases = [ ("can not attack"               , (2, 4), (6, 6), False)
, ("can attack on same rank"      , (2, 4), (2, 6), True )
, ("can attack on same file"      , (4, 5), (2, 5), True )
, ("can attack on first diagonal" , (2, 2), (0, 4), True )
, ("can attack on second diagonal", (2, 2), (3, 1), True )
, ("can attack on third diagonal" , (2, 2), (1, 1), True )
, ("can attack on fourth diagonal", (2, 2), (5, 5), True ) ]

for_ cases test

-- cc646595d39e13c4d310da2629599bcc45e92bd9``````
``````module Queens
( boardString
, canAttack
) where

import           Data.List                      ( intersperse )

boardString :: Maybe (Int, Int) -> Maybe (Int, Int) -> String
boardString w b = unlines (map (intersperse ' ') boardString')
where
emtpyBoard   = replicate 8 (replicate 8 '_')
boardString' = putChess w 'W' (putChess b 'B' emtpyBoard)

canAttack :: (Int, Int) -> (Int, Int) -> Bool
canAttack (r, c) (r', c') = r == r' || c == c' || abs (r - r') == abs (c - c')

putChess :: Maybe (Int, Int) -> Char -> [String] -> [String]
putChess Nothing _ board = board
putChess (Just (r, c)) chess (xs : xss)
| r == 0    = putChessRow c chess xs : xss
| otherwise = xs : putChess (Just (r - 1, c)) chess xss

putChessRow :: Int -> Char -> String -> String
putChessRow c chess (x : xs) | c == 0    = chess : xs
| otherwise = x : putChessRow (c - 1) chess xs``````