Skip to content

Instantly share code, notes, and snippets.

@rsgrafx
Created May 7, 2018 01:36
Show Gist options
  • Save rsgrafx/7f0554cec6f7980befc84db125886f4b to your computer and use it in GitHub Desktop.
Save rsgrafx/7f0554cec6f7980befc84db125886f4b to your computer and use it in GitHub Desktop.
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