Queen Attack Exercism solution
defmodule Queens do | |
@type t :: %Queens{black: {integer, integer}, white: {integer, integer}, grid: List.t()} | |
defstruct black: nil, white: nil, grid: nil | |
@doc """ | |
Creates a new set of Queens | |
""" | |
@spec new({integer, integer}, {integer, integer}, integer) :: t() | |
def new(white \\ {0, 3}, black \\ {7, 3}, grid \\ 8) | |
def new(white, white, _grid_size) do | |
raise(ArgumentError) | |
end | |
def new(white, black, grid_size) do | |
struct(Queens, white: white, black: black, grid: chess_grid(grid_size)) | |
end | |
@doc """ | |
Gives a string reprentation of the board with | |
white and black queen locations shown | |
""" | |
@spec to_string(t()) :: String.t() | |
def to_string(queens) do | |
queens.grid | |
|> Enum.map(&build_row(&1, queens)) | |
|> to_string_trim("\n") | |
end | |
# [ | |
# [{0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6}], | |
# [{1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6}], | |
# [{2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6}], | |
# [{3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6}], | |
# [{4,0},{4,1},{4,2},{4,3},{4,4},{4,5},{4,6}], | |
# [{5,0},{5,1},{5,2},{5,3},{5,4},{5,5},{5,6}], | |
# [{6,0},{6,1},{6,2},{6,3},{6,4},{6,5},{6,6}] | |
# ] | |
defp chess_grid(val) do | |
val = val - 1 | |
for n <- 0..val, do: for(z <- 0..val, do: {n, z}) | |
end | |
defp build_row(row, %{white: white, black: black}) do | |
row_count = length(row) - 1 | |
row | |
|> Enum.with_index() | |
|> Enum.map(fn | |
{^white, ^row_count} -> "W\n" | |
{^black, ^row_count} -> "B\n" | |
{^white, _} -> "W " | |
{^black, _} -> "B " | |
{_, ^row_count} -> "_\n" | |
_ -> "_ " | |
end) | |
|> to_string_trim(" ") | |
end | |
@doc """ | |
Checks if the queens can attack each other | |
""" | |
@spec can_attack?(t()) :: boolean | |
def can_attack?(%{white: {w, _}, black: {b, _}}) when w == b, do: true | |
def can_attack?(%{white: {_, w}, black: {_, b}}) when w == b, do: true | |
def can_attack?(%{white: white, black: black}) do | |
slantL = diagonal_left(white) | |
slantR = diagonal_right(white) | |
Enum.member?(slantL, black) || Enum.member?(slantR, black) | |
end | |
# Private Functions | |
defp diagonal_left({row, col}) do | |
for(n <- 0..(6 - row), do: {n + row, n + col}) ++ for n <- 1..row, do: {row - n, col - n} | |
end | |
defp diagonal_right({row, col}) do | |
for(n <- 0..(6 - row), do: {row + n, col - n}) ++ for n <- 1..row, do: {row - n, col + n} | |
end | |
defp to_string_trim(value, char) do | |
value | |
|> Kernel.to_string() | |
|> String.trim(char) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment