Skip to content

Instantly share code, notes, and snippets.

@hickford
Last active May 15, 2023 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hickford/26fb717a3fe40c66709c8f3457b180c5 to your computer and use it in GitHub Desktop.
Save hickford/26fb717a3fe40c66709c8f3457b180c5 to your computer and use it in GitHub Desktop.
// solve a problem by backtracking
let solveByBacktracking solved moves initialState =
let rec inner state =
// to do: backtrack immediately if arrive at state we've seen before. (This can't happen for knight's tour or n queens as below.)
match state with
| Some progress when (progress |> solved |> not) ->
progress |> moves |> Seq.map (Some >> inner) |> Seq.tryFind Option.isSome |> Option.flatten
| _ -> state
initialState |> Some |> inner
// search for an example of knight's tour on n by m board
let knightsTour (n,m) =
let solved progress = (List.length progress) = n*m
let moves progress =
match progress with
| [] ->
seq {for i in [0..n-1] do for j in [0..m-1] do yield [(i, j)]}
| (i, j)::_ ->
let onBoard (i,j) =
0 <= i && i < n && 0 <= j && j < m
let relativeMoves = [(1,2); (1,-2); (2,1); (2,-1); (-1, 2); (-1, -2); (-2, 1); (-2, -1)]
let prepend pos = pos :: progress
let novel pos = progress |> List.contains pos |> not
relativeMoves |> Seq.map (fun (x,y) -> (x+i, y+j)) |> Seq.filter onBoard |> Seq.filter novel |> Seq.map prepend
[] |> solveByBacktracking solved moves
// solve n queens problem. place n queens on an n x n board such that none threaten each other. returns row of each queen by column.
let queens n =
let legal rows =
// check that no queens are threatening each other
let n = rows |> Seq.length
let areDistinct = Seq.distinct >> Seq.length >> (=) n
let forwardDiagonals = rows |> Seq.mapi (+)
let backDiagonals = rows |> Seq.mapi (-)
rows |> areDistinct && forwardDiagonals |> areDistinct && backDiagonals |> areDistinct
let solved progress = (List.length progress) = n
let moves progress =
let prepend x = x::progress
[0..n-1] |> Seq.map prepend |> Seq.filter legal
[] |> solveByBacktracking solved moves
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment