Решение логических задач на Lisp
Формулировка задачи:
Создаю повторно тему, с прошлой возникли какие-то технические трудности. Суть задачи в следующем:
К реке подъехали 4 рыцаря с оруженосцами и обнаружили одну трехместную лодку. Как им переправиться на другой берег, если все оруженосцы наотрез отказались оставаться в обществе незнакомых рыцарей? Прошу помощи с решением данной задачи, если у вас есть готовое решение, то буду очень признателен. Если нет, то помоги хоть идеей. Мне удалось сделать
;Функция opposite позволяет менять местоположение путника
;Функция path должна реализовывать как раз поиск в глубину и возвращать путь
Как составить эту функцию? С этим и возникли основные трудности.
Буду очень признателен за помощь.
(defun opposite(side) (cond ((equal side 'e) 'w) ((equal side 'w) 'e) ) ) ;Функция takes позволяет перевозить в лодке пассажиров, но генерирует много ненужных последовательностей (defun takes (state n1 n2 n3) (labels ((test(state num1 num2 num3 e boat) (cond ((null state) nil) ((= e 0)(if (and (> num1 -1)(> num2 -1)(> num3 -1)) (if (and (equal (nth num1 state) (nth num2 state)) (equal (nth num1 state) (nth num3 state)) (equal (nth num1 state) (car (last state)))) (test state num1 num2 num3 (+ e 1) boat) nil ) )) ((= 0 num1)(append (list(opposite (nth 0 state))) (test (cdr state) (setf num1 -1) (- num2 1)(- num3 1) e (- boat 1)))) ((= 0 num2)(append (list(opposite (nth 0 state))) (test (cdr state) (- num1 1) (setf num2 -1)(- num3 1) e (- boat 1)))) ((= 0 num3)(append (list(opposite (nth 0 state))) (test (cdr state) (- num1 1) (- num2 1)(setf num3 -1) e (- boat 1)))) ((= 0 boat)(append (list(opposite (nth 0 state))))) (t (append (list (car state)) (test (cdr state) (- num1 1)(- num2 1)(- num3 1) e (- boat 1)))) ) ) ) (test state n1 n2 n3 0 (- (length state) 1)) ) ) ;Функция testiter перебирает всевозможные комбинации из трех чисел. Первым параметром приходит тот, кто перевозит - он не изменяется. (defun testiter (state n n1 n2) (cond ((> n2 (- (length state) 2)) nil) ((> n1 (- (length state) 2)) (append (list (takes state n n1 n2)) (testiter state n 0 (+ n2 1)))) (t (append (list (takes state n n1 n2))(testiter state n (+ n1 1) n2))) ) ) ;Функция del удаляет одинаковые комбинации ходов. (defun del(lst) (labels( (temp (a b len) (cond ((null a) nil) ((equal (car a) (car b))(temp (cdr a) (cddr a) (- (length lst) 1))) ((= len 0) (append (list (car a))(temp (cdr a) (cddr a) (- (length lst) 1)))) (t (temp a (cdr b) (- len 1))) ) ) ) (temp lst (cdr lst) (- (length lst) 1)) ) ) ; Функции *-side возвращают, где находится тот или иной путник. (defun r1-side (state)(nth 0 state)) (defun r2-side (state)(nth 1 state)) (defun r3-side (state)(nth 2 state)) (defun r4-side (state)(nth 3 state)) (defun o1-side (state)(nth 4 state)) (defun o2-side (state)(nth 5 state)) (defun o3-side (state)(nth 6 state)) (defun o4-side (state)(nth 7 state)) (defun o4-side (state)(nth 8 state)) ;Функция safe проверяет, можно ли сделать ход. Суть состоит в том, что происходит проверка, если рыцарь и оруженосец на разных берегах и какой-то рыцарь на берегу с этим оруженосцем. (defun safe (state) (cond ((and (or (equal (r2-side state) (o1-side state)) (equal (r3-side state) (o1-side state))(equal (r4-side state) (o1-side state)))(not (equal (r1-side state) (o1-side state)))) nil) ((and (or (equal (r1-side state) (o2-side state)) (equal (r3-side state) (o2-side state))(equal (r4-side state) (o2-side state)))(not (equal (r2-side state) (o2-side state)))) nil) ((and (or (equal (r2-side state) (o3-side state)) (equal (r1-side state) (o3-side state))(equal (r4-side state) (o3-side state)))(not (equal (r3-side state) (o3-side state)))) nil) ((and (or (equal (r2-side state) (o4-side state)) (equal (r3-side state) (o4-side state))(equal (r1-side state) (o4-side state)))(not (equal (r4-side state) (o4-side state)))) nil) (t state) ) ) ;Функция checkSafe данная функция применяет функцию safe к каждому элементу списка (defun checkSafe(lst) (cond ((null lst) nil) (t (append (list (safe (car lst))) (checkSafe (cdr lst)))) ) ) ;Функция pos_move возвращает ходы, которые применимы для входящего состояния (defun pos_move(state) (del (append (remove 'NIL (checkSafe (del (testiter state 0 0 0)))) (remove 'NIL (checkSafe (del (testiter state 1 0 0)))) (remove 'NIL (checkSafe (del (testiter state 2 0 0)))) (remove 'NIL (checkSafe (del (testiter state 3 0 0)))) (remove 'NIL (checkSafe (del (testiter state 4 0 0)))) (remove 'NIL (checkSafe (del (testiter state 5 0 0)))) (remove 'NIL (checkSafe (del (testiter state 6 0 0)))) (remove 'NIL (checkSafe (del (testiter state 7 0 0)))) ) ) ) ;Функция checkGoal проверяет есть ли в списке возможных ходов, наше целевое значение, если да возвращает true, иначе nil (defun checkGoal (state goal) (cond ((null state) nil) ((equal (car state) goal) T) (t (checkGoal (cdr state) goal)) ) )
Решение задачи: «Решение логических задач на Lisp»
textual
Листинг программы
;Функция opposite позволяет менять местоположение путника (defun opposite(side) (cond ((equal side 'e) 'w) ((equal side 'w) 'e) ) ) ;Функция takes позволяет перевозить в лодке пассажиров, но генерирует много ненужных последовательностей (defun takes (state n1 n2 n3) (labels ((test(state num1 num2 num3 e boat) (cond ((null state) nil) ((= e 0)(if (and (> num1 -1)(> num2 -1)(> num3 -1)) (if (and (equal (nth num1 state) (nth num2 state)) (equal (nth num1 state) (nth num3 state)) (equal (nth num1 state) (car (last state)))) (test state num1 num2 num3 (+ e 1) boat) nil ) )) ((= 0 num1)(append (list(opposite (nth 0 state))) (test (cdr state) (setf num1 -1) (- num2 1)(- num3 1) e (- boat 1)))) ((= 0 num2)(append (list(opposite (nth 0 state))) (test (cdr state) (- num1 1) (setf num2 -1)(- num3 1) e (- boat 1)))) ((= 0 num3)(append (list(opposite (nth 0 state))) (test (cdr state) (- num1 1) (- num2 1)(setf num3 -1) e (- boat 1)))) ((= 0 boat)(append (list(opposite (nth 0 state))))) (t (append (list (car state)) (test (cdr state) (- num1 1)(- num2 1)(- num3 1) e (- boat 1)))) ) ) ) (test state n1 n2 n3 0 (- (length state) 1)) ) ) ;Функция testiter перебирает всевозможные комбинации из трех чисел. Первым параметром приходит тот, кто перевозит - он не изменяется. (defun testiter (state n n1 n2) (cond ((> n2 (- (length state) 2)) nil) ((> n1 (- (length state) 2)) (append (list (takes state n n1 n2)) (testiter state n 0 (+ n2 1)))) (t (append (list (takes state n n1 n2))(testiter state n (+ n1 1) n2))) ) ) ;Функция del удаляет одинаковые комбинации ходов. (defun del(lst) (labels( (temp (a b len) (cond ((null a) nil) ((equal (car a) (car b))(temp (cdr a) (cddr a) (- (length lst) 1))) ((= len 0) (append (list (car a))(temp (cdr a) (cddr a) (- (length lst) 1)))) (t (temp a (cdr b) (- len 1))) ) ) ) (temp lst (cdr lst) (- (length lst) 1)) ) ) ; Функции *-side возвращают, где находится тот или иной путник. (defun r1-side (state)(nth 0 state)) (defun r2-side (state)(nth 1 state)) (defun r3-side (state)(nth 2 state)) (defun r4-side (state)(nth 3 state)) (defun o1-side (state)(nth 4 state)) (defun o2-side (state)(nth 5 state)) (defun o3-side (state)(nth 6 state)) (defun o4-side (state)(nth 7 state)) (defun o4-side (state)(nth 8 state)) ;Функция safe проверяет, можно ли сделать ход. Суть состоит в том, что происходит проверка, если рыцарь и оруженосец на разных берегах и какой-то рыцарь на берегу с этим оруженосцем. (defun safe (state) (cond ((and (or (equal (r2-side state) (o1-side state)) (equal (r3-side state) (o1-side state))(equal (r4-side state) (o1-side state)))(not (equal (r1-side state) (o1-side state)))) nil) ((and (or (equal (r1-side state) (o2-side state)) (equal (r3-side state) (o2-side state))(equal (r4-side state) (o2-side state)))(not (equal (r2-side state) (o2-side state)))) nil) ((and (or (equal (r2-side state) (o3-side state)) (equal (r1-side state) (o3-side state))(equal (r4-side state) (o3-side state)))(not (equal (r3-side state) (o3-side state)))) nil) ((and (or (equal (r2-side state) (o4-side state)) (equal (r3-side state) (o4-side state))(equal (r1-side state) (o4-side state)))(not (equal (r4-side state) (o4-side state)))) nil) (t state) ) ) ;Функция checkSafe данная функция применяет функцию safe к каждому элементу списка (defun checkSafe(lst) (cond ((null lst) nil) (t (append (list (safe (car lst))) (checkSafe (cdr lst)))) ) ) ;Функция pos_move возвращает ходы, которые применимы для входящего состояния (defun pos_move(state) (del (append (remove 'NIL (checkSafe (del (testiter state 0 0 0)))) (remove 'NIL (checkSafe (del (testiter state 1 0 0)))) (remove 'NIL (checkSafe (del (testiter state 2 0 0)))) (remove 'NIL (checkSafe (del (testiter state 3 0 0)))) (remove 'NIL (checkSafe (del (testiter state 4 0 0)))) (remove 'NIL (checkSafe (del (testiter state 5 0 0)))) (remove 'NIL (checkSafe (del (testiter state 6 0 0)))) (remove 'NIL (checkSafe (del (testiter state 7 0 0)))) ) ) ) ;Функция checkGoal проверяет есть ли в списке возможных ходов, наше целевое значение, если да возвращает true, иначе nil (defun checkGoal (state goal) (cond ((null state) nil) ((equal (car state) goal) (car state)) (t (checkGoal (cdr state) goal)) ) ) ;Функция checkWas проверяет есть ли в списке уже пройденных вершин, вершины из списка возможных ходов (defun checkWas (st b) (labels ((temp (state been_list len) (cond ((null state) nil) ((null been_list) state) ((equal (car state) (car been_list)) (temp (cdr state) b (- (length b) 1))) ((= len 0) (append (list (car state)) (temp (cdr state) b (- (length b) 1)))) (t (temp state (cdr been_list) (- len 1))) ) )) (temp st b (- (length b) 1)) ) ) ;Функция path (defun path(state goal been_list) (cond ((null state) nil) ((not (null (checkGoal been_list goal))) (reverse (cons (checkGoal state goal) been_list))) ((not (null (checkGoal state goal))) (reverse (cons (checkGoal state goal) been_list))) ((not (null (checkWas state been_list))) (or (path (pos_move (car (checkWas state been_list))) goal (cons (car (checkWas state been_list)) been_list)) (path (cdr (checkWas state been_list)) goal been_list) ) ) ) ) (print (path '((w w w w w w w w w)) '(e e e e e e e e e) nil))
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д