Задача о восьми ферзях - это классический пример проблемы, которая решается перебором вариантов. Задача сама по себе, как и задача о Ханойских башнях, весьма интересна, а ее решение показывает несколько важных алгоритмических приемов.
Каркас процедуры решения за нас уже определили заботливые авторы, нам же осталось только задать представление позиций на доске константой empty-board и процедурой adjoin-position, а также реализовать проверку безопасности позиции процедурой-предикатом safe?.
Я предлагаю хранить позиции как списки номеров горизонталей, в которых располагаются ферзи. Список позиций тогда задается списком таких списков. Пустая доска обозначается пустым списком (списком из нуля элементов, так как на доске расставлено 0 ферзей). Для удобства операций при описании позиции ферзи в списке будут перечисляться в обратном порядке (от последнего добавленного к первому). Можно также описать такое задание как движение не слева направо по вертикалям, а справа налево.
Для пояснения рассмотрим доску 4х4, где ферзи расставлены слева направо во второй, четвертой, первой и третьей горизонталях.

Эта позиция будет задаваться списком (3 1 4 2).
Итак, пустая доска задается пустым списком:
(define empty-board (list))
Для того, чтобы добавить к позиции еще одного ферзя, просто добавим номер горизонтали, на которой он расположен, в начало списка, обозначающего позицию:
(define (adjoin-position new-row k rest-of-queens)
(cons new-row rest-of-queens))
Проверка позиции на безопасность заключается в том, чтобы пройти по всем ферзям с предпоследнего до первого и проверить безопасны ли они для последнего (по построению они гарантированно безопасны друг для друга). Эту задачу выполняет предикат queens-safe?. Проверка того, безопасен ли очередной ферзь для последнего выполняется предикатом queen-safe?, который проверяет два условия:
- стоят ли эти ферзи на одной горизонтали (равенство горизонталей),
- стоят ли эти ферзи на одной диагонали (равенство модуля разности между горизонталями и модулю разности между вертикалями).
Проверку того, стоят ли ферзи на одной вертикали делать не нужно, так как по построению все вертикали гарантированно различны.
Таким образом получаем следующее определение процедуры safe?:
(define (safe? k position)
(define (queens-safe? queen-count rest-rows)
(define (queen-safe? col row)
(let ((last-col k) (last-row (car position)))
(and (not (= last-row row))
(not (= (abs (- last-row row))
(abs (- last-col col)))))))
(cond ((null? rest-rows) true)
((queen-safe? queen-count (car rest-rows))
(queens-safe? (- queen-count 1) (cdr rest-rows)))
(else false)))
(queens-safe? (- k 1) (cdr position)))
Собирая результат воедино, получим для доски 4х4 следующие две безопасные позиции:
> (queens 4)
((3 1 4 2) (2 4 1 3))
Для доски 5х5 существует 10 различных решений. Для доски 6х6 количество решений меньше, всего 4. Для доски 7х7 есть уже 40 решений. Для доски 8х8 ферзей можно расставить 92 способами. Доска 9х9 допускает 352 различных расстановки, а 10х10 - 724.
Одно из решений (первое, которое выдает наша программа) задачи о восьми ферзях (то есть для доски 8х8) изображено ниже:

Правда, интересная задачка?