ハノイの塔
30分プログラム、その366。ハノイの塔を解いてみる。
そういえば、ハノイの塔は解いたことがなかったので、いまさらチャレンジしてみる。
Wikipediaを見たら、引数の順序を入れかえて一つの関数で済ませていたので、混乱してしまった。そこで、引数の順序を固定して、動かすパターン(AからBへ、など)ごとに関数を定義してみた。量がすごいことになったので、やっぱりWikipediaに書いてあるほうがスマートだ。
ところで、ハノイって実在の地名だったんだ・・・。
使い方
gosh> (hanoi 3) ((2 3) () (1)) ((3) (2) (1)) ((3) (1 2) ()) (() (1 2) (3)) ((1) (2) (3)) ((1) () (2 3)) (() () (1 2 3))
ソースコード
#! /opt/local/bin/gosh ;; -*- mode:scheme; coding:utf-8 -*- ;; ;; hanoi.scm - ;; ;; Copyright(C) 2008 by mzp ;; Author: MIZUNO Hiroki / mzpppp at gmail dot com ;; http://howdyworld.org ;; ;; Timestamp: 2008/09/16 21:59:39 ;; ;; This program is free software; you can redistribute it and/or ;; modify it under MIT Lincence. ;; (use srfi-1) (define (make-tower n) (iota n 1)) (define (one? xs) (eq? (cdr xs) '())) (define (pull a) (cdr a)) (define (push a b) (cons (car a) b)) (define (list-x . x) (print x) x) ;; a => {b,c} (define (a=>b n a b c) (if (= n 1) (list-x (pull a) (push a b) c) (let* [(t1 (a=>c (- n 1) a b c)) (t2 (apply a=>b 1 t1)) (t3 (apply c=>b (- n 1) t2))] t3))) (define (a=>c n a b c) (if (= n 1) (list-x (pull a) b (push a c)) (let* [(t1 (a=>b (- n 1) a b c)) (t2 (apply a=>c 1 t1)) (t3 (apply b=>c (- n 1) t2))] t3))) ;; b => {c,a} (define (b=>c n a b c) (if (= n 1) (list-x a (pull b) (push b c)) (let* [(t1 (b=>a (- n 1) a b c)) (t2 (apply b=>c 1 t1)) (t3 (apply a=>c (- n 1) t2))] t3))) (define (b=>a n a b c) (if (= n 1) (list-x (push b a) (pull b) c) (let* [(t1 (b=>c (- n 1) a b c)) (t2 (apply b=>a 1 t1)) (t3 (apply c=>a (- n 1) t2))] t3))) ;; c => {a,b} (define (c=>a n a b c) (if (= n 1) (list-x (push c a) b (pull c)) (let* [(t1 (c=>b (- n 1) a b c)) (t2 (apply c=>a 1 t1)) (t3 (apply b=>a (- n 1) t2))] t3))) (define (c=>b n a b c) (if (= n 1) (list-x a (push c b) (pull c)) (let* [(t1 (c=>a (- n 1) a b c)) (t2 (apply c=>b 1 t1)) (t3 (apply a=>b (- n 1) t2))] t3))) (define (hanoi n) (define a (make-tower n)) (define b (make-tower 0)) (define c (make-tower 0)) (a=>c n a b c))