Ханойские башни Common Lisp
Формулировка задачи:
Есть 3 стержня, на один из которых нанизаны 8 дисков, причем диски отличаются размером и лежат меньшее на большем. Задача состоит в том,чтобы перенести пирамиду из n-дисков за наименьшее число ходов. За один раз можно перенести только 1 диск, причем нельзя класть больший на меньший.
Все это реализуется с помощью списков и поиска в ширину. На Common Lisp
Кто-нибудь знает как это сделать?
я нашла такое задание на scheme, но в common lisp переделать не получается
на scheme
Листинг программы
- ;;; Создание колышка
- (define (peg token count)
- ;; Список p - это "внутренняя структура" колышка
- (let ((p (reverse (generaten count))))
- (define (display-peg)
- (display token)
- (display ": ")
- (display p)
- (newline))
- (define (push-ring! ring)
- (set! p (cons ring p))
- (display-peg))
- (define (pop-ring!)
- (let ((ring (car p)))
- (set! p (cdr p))
- (display-peg)
- ring))
- (define (peg-token)
- token)
- (define (height)
- (length p))
- (lambda (mes)
- (cond ((eq? mes 'display)
- (display-peg))
- ((eq? mes 'push-ring)
- push-ring!)
- ((eq? mes 'pop-ring)
- (pop-ring!))
- ((eq? mes 'token)
- (peg-token))
- ((eq? mes 'height)
- (height))
- (else
- error "peg -- неизвестное сообщение" mes)))))
- ;;; Печать колышка
- (define (display-peg peg)
- (peg 'display))
- ;;; Поместить кольцо на колышек
- (define (push-ring! peg ring)
- ((peg 'push-ring) ring))
- ;;; Изъять кольцо с колышка
- (define (pop-ring! peg)
- (peg 'pop-ring))
- ;;; Метка данного колышка
- (define (peg-token peg)
- (peg 'token))
- ;;; Высота (число колец) колышка
- ;;; (для решения задачи так и не понадобилась)
- (define (peg-height peg)
- (peg 'height))
- ;;; Вспомогательная функция
- ;;; создает список из убывающих чисел от number до 1 (включительно)
- (define (generaten number)
- (if (= 0 number)
- '()
- (cons number (generaten (- number 1)))))
- ;;; Функция переноса кольца с колышка peg-from на колышек peg-to
- (define (move peg-from peg-to peg)
- (display "Перенос кольца с колышка '")
- (display (peg-token peg-from))
- (display "' на колышек '")
- (display (peg-token peg-to))
- (display "':")
- (newline)
- (push-ring! peg-to (pop-ring! peg-from))
- * (display-peg peg))
- (define (hanoi-tower height)
- (let ((a (peg 'a height))
- (b (peg 'b 0))
- (c (peg 'c 0)))
- (display "Состояние колышков до переноса:")
- (newline)
- (display-peg a)
- (display-peg b)
- (display-peg c)
- ;;; Вся полезная работа происходит тут
- (let hanoi ((peg-a a)
- (peg-b b)
- (peg-c c)
- (n height))
- (cond ((not (= n 0))
- (hanoi peg-a peg-c peg-b (- n 1))
- (move peg-a peg-c peg-b)
- (hanoi peg-b peg-a peg-c (- n 1))))))
- 'конец)
- вывод
- > (hanoi-tower 4)
- Состояние колышков до переноса:
- a: (1 2 3 4)
- b: ()
- c: ()
- Перенос кольца с колышка 'a' на колышек 'b':
- a: (2 3 4)
- b: (1)
- c: ()
- Перенос кольца с колышка 'a' на колышек 'c':
- a: (3 4)
- c: (2)
- b: (1)
- Перенос кольца с колышка 'b' на колышек 'c':
- b: ()
- c: (1 2)
- a: (3 4)
- Перенос кольца с колышка 'a' на колышек 'b':
- a: (4)
- b: (3)
- c: (1 2)
- Перенос кольца с колышка 'c' на колышек 'a':
- c: (2)
- a: (1 4)
- b: (3)
- Перенос кольца с колышка 'c' на колышек 'b':
- c: ()
- b: (2 3)
- a: (1 4)
- Перенос кольца с колышка 'a' на колышек 'b':
- a: (4)
- b: (1 2 3)
- c: ()
- Перенос кольца с колышка 'a' на колышек 'c':
- a: ()
- c: (4)
- b: (1 2 3)
- Перенос кольца с колышка 'b' на колышек 'c':
- b: (2 3)
- c: (1 4)
- a: ()
- Перенос кольца с колышка 'b' на колышек 'a':
- b: (3)
- a: (2)
- c: (1 4)
- Перенос кольца с колышка 'c' на колышек 'a':
- c: (4)
- a: (1 2)
- b: (3)
- Перенос кольца с колышка 'b' на колышек 'c':
- b: ()
- c: (3 4)
- a: (1 2)
- Перенос кольца с колышка 'a' на колышек 'b':
- a: (2)
- b: (1)
- c: (3 4)
- Перенос кольца с колышка 'a' на колышек 'c':
- a: ()
- c: (2 3 4)
- b: (1)
- Перенос кольца с колышка 'b' на колышек 'c':
- b: ()
- c: (1 2 3 4)
- a: ()
- конец
Решение задачи: «Ханойские башни Common Lisp»
textual
Листинг программы
- (defn hanoi (n)
- (print "ЗАДАЧА - ханойские башни, n = " n ":" \n)
- (defn try-move (f t)
- cond (null? f) false
- (or (null? t) (< (car f) (car t))) (cons (cdr f) (cons (car f) t) nil)
- false)
- (defn steps (chain)
- (match (car chain) '(a b c))
- (def vars (cons
- (cond (match (try-move a b) '(f t)) (cons f t c nil) nil)
- (cond (match (try-move a c) '(f t)) (cons f b t nil) nil)
- (cond (match (try-move b a) '(f t)) (cons t f c nil) nil)
- (cond (match (try-move b c) '(f t)) (cons a f t nil) nil)
- (cond (match (try-move c a) '(f t)) (cons t b f nil) nil)
- (cond (match (try-move c b) '(f t)) (cons a t f nil) nil)
- nil))
- (def nexts (filter (lambda (x) not (null? x)) vars))
- (map (lambda (n) cons n chain) (filter (lambda (v) not (elem v chain)) nexts)))
- (defn solved? (state)
- (match (car state) '(a b c))
- (and (null? a) (null? b)))
- (def start-state (cons (cons (list-from-to 1 n) nil nil nil) nil))
- (defn show-line (l) foldl (lambda (x a) print x " ") 0 l)
- (defn show-res (l i)
- (print \n "Вариант " i ":" \n)
- (defn go (l) cond (null? l) (+ i 1) ((show-line (car l)) (print \n) (go (cdr l)) ))
- (go l))
- (print "Поиск в глубину:")
- (show-res (reverse (solve-depth steps solved? start-state)) 1)
- (print \n "Поиск в ширину:" \n)
- (foldl (lambda (l a) show-res (reverse l) a) 1 (solve-wide steps solved? start-state)) )
- (hanoi 4)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д