Created
February 18, 2012 22:13
-
-
Save qsorix/1861138 to your computer and use it in GitHub Desktop.
Tower of Hanoi in Haskell, part 4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Control.Monad.State | |
| import Data.Lens.Common | |
| type Disc = Int | |
| type Tower = [Disc] | |
| data Towers = Towers | |
| { towerA_ :: Tower | |
| , towerB_ :: Tower | |
| , towerC_ :: Tower | |
| } deriving (Show) | |
| data TowerName = A | B | C | |
| deriving (Show) | |
| type Move = (TowerName, TowerName) | |
| type TowersState = State Towers | |
| type TowerLens = Lens Towers Tower | |
| data Pointer = Pointer TowerName TowerLens | |
| ptrA = Pointer A (lens towerA_ (\a s -> s { towerA_ = a})) | |
| ptrB = Pointer B (lens towerB_ (\a s -> s { towerB_ = a})) | |
| ptrC = Pointer C (lens towerC_ (\a s -> s { towerC_ = a})) | |
| pop :: TowerLens -> TowersState Disc | |
| pop lense = do | |
| (x:xs) <- gets (getL lense) | |
| modify $ lense `setL` xs | |
| return x | |
| push :: Disc -> TowerLens -> TowersState () | |
| push d lense = modify $ lense `modL` (\xs -> d:xs) | |
| moveOne :: Pointer -> Pointer -> TowersState [Move] | |
| moveOne (Pointer nsrc src) (Pointer ndst dst) = | |
| pop src >>= | |
| (flip push) dst >> | |
| return [(nsrc, ndst)] | |
| moveMany :: Int -> Pointer -> Pointer -> Pointer -> TowersState [Move] | |
| moveMany 1 src dst aux = moveOne src dst | |
| moveMany n src dst aux = do | |
| m1 <- moveMany (n-1) src aux dst | |
| m2 <- moveMany 1 src dst aux | |
| m3 <- moveMany (n-1) aux dst src | |
| return (m1++m2++m3) | |
| solve :: Towers -> ([Move], Towers) | |
| solve towers = | |
| let count = length $ towerA_ towers | |
| in runState (moveMany count ptrA ptrB ptrC) towers | |
| towers = Towers [1, 2, 3, 4] [] [] | |
| main = putStrLn $ show $ solve towers |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment