How to resolve the algorithm N-queens problem step by step in the Racket programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm N-queens problem step by step in the Racket programming language
Table of Contents
Problem Statement
Solve the eight queens puzzle.
You can extend the problem to solve the puzzle with a board of size NxN. For the number of solutions for small values of N, see OEIS: A000170.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm N-queens problem step by step in the Racket programming language
Source code in the racket programming language
#lang racket
(struct Q (x y) #:transparent)
;; returns true if given q1 and q2 do not conflict
(define (safe? q1 q2)
(match* (q1 q2)
[((Q x1 y1) (Q x2 y2))
(not (or (= x1 x2) (= y1 y2)
(= (abs (- x1 x2)) (abs (- y1 y2)))))]))
;; returns true if given q doesn't conflict with anything in given list of qs
(define (safe-lst? q qs) (for/and ([q2 qs]) (safe? q q2)))
(define (nqueens n)
;; qs is partial solution; x y is current position to try
(let loop ([qs null] [x 0] [y 0])
(cond [(= (length qs) n) qs] ; found a solution
[(>= x n) (loop qs 0 (add1 y))] ; go to next row
[(>= y n) #f] ; current solution is invalid
[else
(define q (Q x y))
(if (safe-lst? q qs) ; is current position safe?
(or (loop (cons q qs) 0 (add1 y)) ; optimistically place a queen
; (and move pos to next row)
(loop qs (add1 x) y)) ; backtrack if it fails
(loop qs (add1 x) y))])))
(nqueens 8)
; => (list (Q 3 7) (Q 1 6) (Q 6 5) (Q 2 4) (Q 5 3) (Q 7 2) (Q 4 1) (Q 0 0))
(require htdp/show-queen)
(define (show-nqueens n)
(define qs (time (nqueens n)))
(show-queen
(for/list ([row n])
(for/list ([col n])
(if (member (Q row col) qs) #t #f)))))
(show-nqueens 8)
#lang racket
(struct Q (x y) #:transparent)
(define-syntax-rule (lcons x y) (cons x (lazy y)))
(define (lazy-filter p? lst)
(define flst (force lst))
(if (null? flst) '()
(let ([x (car flst)])
(if (p? x)
(lcons x (lazy-filter p? (cdr flst)))
(lazy-filter p? (cdr flst))))))
(define (lazy-foldr f base lst)
(define flst (force lst))
(if (null? flst) base
(f (car flst) (lazy (lazy-foldr f base (cdr flst))))))
(define (tails lst)
(if (null? lst) '(())
(cons lst (tails (cdr lst)))))
(define (safe? q1 q2)
(match* (q1 q2)
[((Q x1 y1) (Q x2 y2))
(not (or (= x1 x2) (= y1 y2)
(= (abs (- x1 x2)) (abs (- y1 y2)))))]))
(define (safe-lst? lst)
(or (null? lst)
(let ([q1 (car lst)])
(for/and ([q2 (cdr lst)]) (safe? q1 q2)))))
(define (valid? lst) (andmap safe-lst? (tails lst)))
(define (nqueens n)
(define all-possible-solutions
(for/fold ([qss-so-far '(())]) ([row (in-range n)])
(lazy-foldr
(λ (qs new-qss)
(append (for/list ([col (in-range n)]) (cons (Q row col) qs))
new-qss))
'() qss-so-far)))
(lazy-filter valid? all-possible-solutions))
(car (nqueens 8))
;; => (list (Q 7 3) (Q 6 1) (Q 5 6) (Q 4 2) (Q 3 5) (Q 2 7) (Q 1 4) (Q 0 0))
(define (force-and-print qs)
(define forced (force qs))
(unless (null? forced)
(printf "~v\n" (car forced))
(force-and-print (cdr forced))))
(force-and-print (nqueens 8))
; =>
;(list (Q 7 3) (Q 6 1) (Q 5 6) (Q 4 2) (Q 3 5) (Q 2 7) (Q 1 4) (Q 0 0))
;(list (Q 7 4) (Q 6 1) (Q 5 3) (Q 4 6) (Q 3 2) (Q 2 7) (Q 1 5) (Q 0 0))
;(list (Q 7 2) (Q 6 4) (Q 5 1) (Q 4 7) (Q 3 5) (Q 2 3) (Q 1 6) (Q 0 0))
;(list (Q 7 2) (Q 6 5) (Q 5 3) (Q 4 1) (Q 3 7) (Q 2 4) (Q 1 6) (Q 0 0))
...
;(list (Q 7 5) (Q 6 3) (Q 5 6) (Q 4 0) (Q 3 2) (Q 2 4) (Q 1 1) (Q 0 7))
;(list (Q 7 3) (Q 6 6) (Q 5 4) (Q 4 1) (Q 3 5) (Q 2 0) (Q 1 2) (Q 0 7))
;(list (Q 7 4) (Q 6 6) (Q 5 1) (Q 4 5) (Q 3 2) (Q 2 0) (Q 1 3) (Q 0 7))
#lang racket
(define (remove x lst)
(for/list ([i (in-range (length lst))]
#:when (not (= x i)))
(list-ref lst i)))
(define (switch-pairs lst)
(cond [(null? lst) '()]
[(null? (cdr lst)) (list '() (car lst))]
[else (append (list (cadr lst) (car lst))
(switch-pairs (cddr lst)))]))
(define (switch-places a1 a2 lst)
(for/list ([i (length lst)])
(list-ref lst (cond [(= a1 i) a2] [(= a2 i) a1] [else i]))))
(define (position-queens n)
(cond [(= 1 n) (list (list 1))]
[(> 4 n) #f]
[else (possible-queens n)]))
(define (possible-queens n)
(define rem (remainder n 12))
(define lst (build-list n add1))
(define evens (filter even? lst))
(define odds (filter odd? lst))
(cond [(or (= rem 9) (= rem 3)) (case3or9 evens odds)]
[(= rem 8) (case8 evens odds)]
[(= rem 2) (case2 evens odds)]
[else (append evens odds)]))
(define (case3or9 evens odds)
(for/fold ([acum (append (cdr evens) (list (car evens)) odds)])
([i (in-list '(1 3))])
(append (remove (list-ref acum i) acum) (list i))))
(define (case8 evens odds)
(append evens (switch-pairs odds)))
(define (case2 evens odds)
(define nums (append evens odds))
(define idx (map (λ(i) (list-ref nums i)) '(1 3 5)))
(append (remove (caddr idx)
(switch-places (car idx) (cadr idx) nums))
'(5)))
(define (queens n)
(define position-numbers (position-queens n))
(define positions-on-board
(for/list ([i n]) (cons i (sub1 (list-ref position-numbers i)))))
(for/list ([x n])
(for/list ([y n])
(if (member (cons x y) positions-on-board) "Q" "."))))
(define (print-queens n)
(for ([x (queens n)]) (displayln (string-join x))))
You may also check:How to resolve the algorithm Empty directory step by step in the UNIX Shell programming language
You may also check:How to resolve the algorithm Next highest int from digits step by step in the Haskell programming language
You may also check:How to resolve the algorithm Quaternion type step by step in the Tcl programming language
You may also check:How to resolve the algorithm Binary strings step by step in the PL/I programming language
You may also check:How to resolve the algorithm Boolean values step by step in the Rust programming language