Mob coding through hanoi problem, discovered need for state tracking and tests are busted

This commit is contained in:
Logan McGrath 2021-10-06 12:12:47 -07:00
parent 5462d22be8
commit 6d5e78c0a9
4 changed files with 50 additions and 27 deletions

View File

@ -34,7 +34,6 @@ library
ghc-options: -Wall -Werror -Wcompat -Widentities -Wincomplete-patterns -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wname-shadowing -Wpartial-fields -Wredundant-constraints -Wunused-packages -Wunused-type-patterns ghc-options: -Wall -Werror -Wcompat -Widentities -Wincomplete-patterns -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-home-modules -Wname-shadowing -Wpartial-fields -Wredundant-constraints -Wunused-packages -Wunused-type-patterns
build-depends: build-depends:
base >=4.14 && <5 base >=4.14 && <5
, unordered-containers
default-language: Haskell2010 default-language: Haskell2010
executable homework executable homework

View File

@ -1,26 +1,38 @@
module Homework.Ch01.Hanoi where module Homework.Ch01.Hanoi where
import qualified Data.HashMap.Strict as HashMap
newtype Peg = Peg () newtype Peg = Peg ()
data Move = Move {moveFrom :: String, moveTo :: String} deriving (Eq, Show) data Move = Move {moveFrom :: String, moveTo :: String} deriving (Eq, Show)
data Disc = Disc {discSize :: Int} data Disc = Disc {discSize :: Int} deriving (Eq, Show, Ord)
type Pegs = [(String, [Disc])]
hanoi :: Int -> String -> String -> String -> Either String [Move] hanoi :: Int -> String -> String -> String -> Either String [Move]
hanoi numDisks pegLabelA pegLabelB pegLabelC = hanoi numDisks pegLabelA pegLabelB pegLabelC =
let _pegs = let pegs =
HashMap.fromList [ (pegLabelA, fillPegWithDiscs numDisks),
[ (pegLabelA, fillPegWithDiscs), (pegLabelB, []),
(pegLabelB, []), (pegLabelC, [])
(pegLabelC, [])
]
in Right
[ Move "a" "c",
Move "a" "b",
Move "c" "b"
] ]
where in Right $ snd $ move pegs
fillPegWithDiscs :: [Disc]
fillPegWithDiscs = Disc <$> [1 .. numDisks] -- start here: make sure this is initialized correctly move :: Pegs -> (Pegs, [Move])
move pegs =
let (firstPegLabel, firstPeg) = head pegs
(lastPegLabel, lastPeg) = last pegs
firstPegDisc = last firstPeg
lastPegDisc = last lastPeg
canMove = firstPegDisc < lastPegDisc
in if canMove
then
( [ (firstPegLabel, init firstPeg),
head $ tail pegs,
(lastPegLabel, lastPeg <> [firstPegDisc])
],
[Move firstPegLabel lastPegLabel]
)
else (pegs, [])
fillPegWithDiscs :: Int -> [Disc]
fillPegWithDiscs numDisks = Disc <$> reverse [1 .. numDisks]

View File

@ -16,8 +16,8 @@ dependencies:
library: library:
source-dirs: lib source-dirs: lib
dependencies: # dependencies:
- unordered-containers # - unordered-containers
executables: executables:
homework: homework:

View File

@ -4,11 +4,23 @@ import Homework.Ch01.Hanoi
import Test.Hspec import Test.Hspec
spec :: Spec spec :: Spec
spec = describe "hanoi" $ do spec = describe "Hanoi" $ do
it "can solve for stack of 2 and three pegs" $ do describe "hanoi" $ do
hanoi 2 "a" "b" "c" it "can solve for a stack of 1 and three pegs" $ do
`shouldBe` Right hanoi 1 "a" "b" "c"
[ Move "a" "c", `shouldBe` Right
Move "a" "b", [Move "a" "c"]
Move "c" "b" it "can solve for stack of 3 and three pegs" $ do
] hanoi 3 "a" "b" "c"
`shouldBe` Right
[ Move "a" "c",
Move "a" "b",
Move "c" "b"
]
describe "fillPegWithDiscs" $ do
it "creates a list of disks from biggest to smallest" $ do
fillPegWithDiscs 3
`shouldBe` [ Disc 3,
Disc 2,
Disc 1
]