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

# minosiants's solution

## to Queen Attack in the Haskell Track

Published at Feb 23 2021 · 0 comments
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

data Side
= White Int Int
| Black Int Int
deriving (Show)

boardString :: Maybe (Int, Int) -> Maybe (Int, Int) -> String
boardString white black =
case (white, black) of
(Just (x, y), Nothing) -> format \$ place (White x y) board
(Just (x, y), Just (x', y')) -> format \$ place (White x y) \$ place (Black x' y') board
(Nothing, Just (x', y')) -> format \$ place (Black x' y') board
(Nothing, Nothing) -> format board
where
place :: Side -> [String] -> [String]
place side brd =
case side of
White x y -> go x y 'W' brd
Black x y -> go x y 'B' brd
go :: Int -> Int -> Char -> [String] -> [String]
go x y ch brd =
let row = brd !! x
row' = take y row ++ [ch] ++ drop (y + 1) row
brd' = take x brd ++ [row'] ++ drop (x + 1) brd
in brd'

canAttack :: (Int, Int) -> (Int, Int) -> Bool
canAttack (x, y) (x', y')
| x == x' = True
| y == y' = True
| abs (x - x') == abs (y - y') = True
| otherwise = False

board :: [String]
board = replicate 8 \$ replicate 8 '_'

format :: [String] -> String
format xs =
unlines \$
fmap (intersperse ' ') xs``````