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

# angelikatyborska's solution

## to Queen Attack in the Elixir Track

Published at May 01 2021 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

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.

## Running tests

Execute the tests with:

``````\$ elixir queen_attack_test.exs
``````

### Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.

For example:

``````# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
``````

Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the test suite.

``````# ExUnit.configure exclude: :pending, trace: true
``````

If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

## 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.

### queen_attack_test.exs

``````if !System.get_env("EXERCISM_TEST_EXAMPLES") do
end

ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)

defmodule QueenAttackTest do
use ExUnit.Case

# @tag :pending
test "default positions" do
queens = Queens.new()
assert queens.white == {0, 3}
assert queens.black == {7, 3}
end

@tag :pending
test "specific placement" do
queens = Queens.new({3, 7}, {6, 1})
assert queens.white == {3, 7}
assert queens.black == {6, 1}
end

@tag :pending
test "cannot occupy same space" do
assert_raise ArgumentError, fn ->
Queens.new({2, 4}, {2, 4})
end
end

@tag :pending
test "string representation" do
queens = Queens.new({2, 4}, {6, 6})

board =
String.trim("""
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ W _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ B _
_ _ _ _ _ _ _ _
""")

assert Queens.to_string(queens) == board
end

@tag :pending
test "another string representation" do
queens = Queens.new({7, 1}, {0, 0})

board =
String.trim("""
B _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ W _ _ _ _ _ _
""")

assert Queens.to_string(queens) == board
end

@tag :pending
test "yet another string representation" do
queens = Queens.new({4, 3}, {3, 4})

board =
String.trim("""
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ B _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
""")

assert Queens.to_string(queens) == board
end

@tag :pending
test "queen placed on the bottom right corner" do
queens = Queens.new({4, 3}, {7, 7})

board =
String.trim("""
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ B
""")

assert Queens.to_string(queens) == board
end

@tag :pending
test "queen placed on the edge of the board" do
queens = Queens.new({4, 3}, {2, 7})

board =
String.trim("""
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ B
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
""")

assert Queens.to_string(queens) == board
end

@tag :pending
test "cannot attack" do
queens = Queens.new({2, 3}, {4, 7})
refute Queens.can_attack?(queens)
end

@tag :pending
test "can attack on same row" do
queens = Queens.new({2, 4}, {2, 7})
assert Queens.can_attack?(queens)
end

@tag :pending
test "can attack on same column" do
queens = Queens.new({5, 4}, {2, 4})
assert Queens.can_attack?(queens)
end

@tag :pending
test "can attack on diagonal" do
queens = Queens.new({1, 1}, {6, 6})
assert Queens.can_attack?(queens)
end

@tag :pending
test "can attack on other diagonal" do
queens = Queens.new({0, 6}, {1, 7})
assert Queens.can_attack?(queens)
end

@tag :pending
test "can attack on yet another diagonal" do
queens = Queens.new({4, 1}, {6, 3})
assert Queens.can_attack?(queens)
end

@tag :pending
test "can attack on a diagonal slanted the other way" do
queens = Queens.new({6, 1}, {1, 6})
assert Queens.can_attack?(queens)
end
end``````
``````defmodule Queens do
@type t :: %Queens{black: {integer, integer}, white: {integer, integer}}
defstruct black: nil, white: nil

@width 8
@white_queen "W"
@black_queen "B"
@empty "_"
@column_delimiter "\n"
@row_delimiter " "

@doc """
Creates a new set of Queens
"""
@spec new() :: Queens.t()
@spec new({integer, integer}, {integer, integer}) :: Queens.t()
def new(white \\ {0, 3}, black \\ {7, 3})
def new({x, y}, {x, y}), do: raise(ArgumentError)

def new({x1, y1}, {x2, y2}) when x1 >= @width or x2 >= @width or y1 >= @width or y2 >= @width do
raise(ArgumentError)
end

def new(white, black) do
%Queens{white: white, black: black}
end

@doc """
Gives a string representation of the board with
white and black queen locations shown
"""
@spec to_string(Queens.t()) :: String.t()
def to_string(queens) do
0..(@width - 1)
|> Enum.map(fn column ->
0..(@width - 1)
|> Enum.map(fn row -> symbol(queens, column, row) end)
|> Enum.join(@row_delimiter)
end)
|> Enum.join(@column_delimiter)
end

@doc """
Checks if the queens can attack each other
"""
@spec can_attack?(Queens.t()) :: boolean
def can_attack?(%Queens{white: {x, _}, black: {x, _}}), do: true
def can_attack?(%Queens{white: {_, y}, black: {_, y}}), do: true

def can_attack?(%Queens{white: {x1, y1}, black: {x2, y2}}) do
abs(x1 - x2) == abs(y1 - y2)
end

defp symbol(%Queens{white: white, black: black}, column, row) do
case {column, row} do
^white -> @white_queen
^black -> @black_queen
_ -> @empty
end
end
end``````