Nanyx

Eight queens

A recursive backtracking search with a local rec function and tagged results.

module eightQueens

def boardSize = 8

-- A partial solution is the column of the queen in each row placed so far.
-- A new queen is safe if no earlier queen shares its column or a diagonal.
def isSafe: (list(int), int) -> bool = { queens, col ->
  queens
    \reverse
    \zip(1..)
    \all { q, distance -> q != col and q != col - distance and q != col + distance }
}

def solve: list(int) -> #some(list(int)) | #noSolution = { queens ->
  if queens.length == boardSize then #some(queens)
  else
    rec tryColumns = {
      | [] -> #noSolution
      | [col, ...rest] ->
        if isSafe(queens, col) then
          match solve([...queens, col])
            | #some(solution) -> #some(solution)
            | #noSolution -> tryColumns(rest)
        else tryColumns(rest)
    }

    tryColumns((0..(boardSize - 1)) \toList)
}

def render: list(int) -> string = { queens ->
  queens
    \map { q -> (0..(boardSize - 1)) \map { c -> if c == q then "Q " else ". " } \String.join("") }
    \String.join("\n")
}

@entry
def main = {
  match solve([])
    | #some(queens) -> println(render(queens))
    | #noSolution -> println("No solution for a {boardSize}x{boardSize} board")
}

This program lives in the repository as examples/eightQueens.nyx.