(##declare (standard-bindings) (not safe) (fixnum)) ; generate fast code
(##declare (multilisp) (futures lazy))              ; use `lazy' futures

(define (queens n trace?)

  (define (1-to n)
    (let loop ((i n) (l '()))
      (if (= i 0) l (loop (- i 1) (cons i l)))))

  (define (try x y z)
    (if (null? x)
      (if (null? y) (begin (if trace? (begin (write z) (newline))) 1) 0)
      (let* ((temp1 (FUTURE (if (ok? (car x) 1 z)
                              (try (append (cdr x) y) '() (cons (car x) z))
                              0)))
             (temp2 (try (cdr x) (cons (car x) y) z)))
        (+ temp1 temp2))))
         

  (define (ok? row dist placed)
    (if (null? placed)
      #t
      (and (not (= (car placed) (+ row dist)))
           (not (= (car placed) (- row dist)))
           (ok? row (+ dist 1) (cdr placed)))))

  (try (1-to n) '() '()))

(define (main)
  (if (> (vector-length ##argv) 1)
    (let ((arg1 (string->number (vector-ref ##argv 1))))
      (if (and arg1 (integer? arg1) (> arg1 0))
        (let ((nb-soln (queens arg1 (> (vector-length ##argv) 2))))
          (display nb-soln)
          (display " solutions")
          (newline))
        (begin
          (display "Argument must be an integer greater than 0")
          (newline))))
    (begin
      (display "Usage: queens n [trace]")
      (newline))))

(main) ; entry point of program...
