Guest User

Towers of Hanoi

a guest
Dec 16th, 2011
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/runghc
  2. import Control.Monad.Writer
  3. import Data.List
  4.  
  5. {-
  6.   Programm um die Zugfolge zur Loesung der Tuerme von Hanoi auszugeben
  7.   http://en.wikipedia.org/wiki/Tower_of_Hanoi
  8. -}
  9.  
  10. -------------------------------------------------------------------------------------
  11.  
  12. -- Benoetigte Datentypen um die Tuerme von Hanoi darzustellen
  13.  
  14. type Hanoi = (Tower,Tower,Tower) -- In Hanoi stehen drei Tuerme. (Das Spielbrett)
  15. type Tower = [Disc] -- Auf diesen Tuermen befinden sich mehrere Scheiben. (Die Tuerme)
  16. type Disc = Int -- Die Scheibengroesse wird als Integer angegeben. (Die Scheiben)
  17. data Position = L | M | R deriving (Eq,Show) -- Position einer Scheibe in Hanoi
  18.  
  19. -------------------------------------------------------------------------------------
  20.  
  21. {- Hilfsfunktion, um die einzelnen Scheiben zu bewegen,
  22.    und die dabei gemachte Bewegung zu Dokumentieren.
  23.    Parameter:
  24.       src: Quellturm
  25.       dst: Zielturm
  26.       h: Spielbrett
  27.    Rueckgabe: Spielbrett mit Anmerkung zum letzten Zug.
  28. -}
  29.  
  30. moveDisc :: Position -> Position -> Hanoi -> Writer [String] Hanoi
  31. -- moveDisc src dst h
  32.  
  33. moveDisc L M (l:ls,m,r) = writer ((ls,l:m,r), [show l++": l->m"])
  34. moveDisc L R (l:ls,m,r) = writer ((ls,m,l:r), [show l++": l->r"])
  35. moveDisc M L (l,m:ms,r) = writer ((m:l,ms,r), [show m++": m->l"])
  36. moveDisc M R (l,m:ms,r) = writer ((l,ms,m:r), [show m++": m->r"])
  37. moveDisc R L (l,m,r:rs) = writer ((r:l,m,rs), [show r++": r->l"])
  38. moveDisc R M (l,m,r:rs) = writer ((l,r:m,rs), [show r++": r->m"])
  39.  
  40. -------------------------------------------------------------------------------------
  41.  
  42. {- Funktion um einen Stapel der Hoehe n von einer Position
  43.    zur Anderen zu bewegen
  44.    Parameter:
  45.      src: Quellturm
  46.      dst: Zielturm
  47.      n: Stapelhoehe
  48.      h: Spielbrett
  49.    Rueckgabe: Spielbrett mit Zuganweisungen.
  50. -}
  51.  
  52. moveStack :: (Integral a) => Position -> Position -> a -> Hanoi -> Writer [String] Hanoi
  53.  
  54. -- Wenn nur eine Scheibe bewegt werden soll, dies ausfuehren:
  55.  
  56. moveStack src dst 1 h = moveDisc src dst h
  57.  
  58.  
  59. -- Bei mehr als einer Scheibe den restlichen Stapel zwischenparken, dann
  60. -- die untere Scheibe transportieren, und den restlichen Stapel nachholen:
  61.  
  62. moveStack src dst n h =
  63.    moveStack src spare (n-1) h >>= moveDisc src dst >>= moveStack spare dst (n-1)
  64.       where spare = head $ [L,M,R] \\ [src,dst] -- unbeteiligten Stapel bestimmen.
  65.  
  66. -------------------------------------------------------------------------------------
  67.  
  68. -- Hauptfunktion, die moveStack mit einem neuen Spielfeld aufruft, so dass
  69. -- die Scheiben am Anfang alle rechts liegen, und von dort nach links transportiert werden.
  70. -- Anschliessend wird die dabei gewonnene Handlungsanweisung ausgegeben.
  71.  
  72. main=putStr $ unlines $ execWriter $ moveStack R L 10 ([],[],[1..10])
Advertisement
Add Comment
Please, Sign In to add comment