module Homework.Ch01.HanoiSpec where import Homework.Ch01.Hanoi import Test.Hspec spec :: Spec spec = describe "Hanoi" $ do -- Testing the solver function describe "hanoi" $ do -- helper to construct a hanoi function with preconfigured labels let hanoiOf = hanoi ["a", "b", "c"] it "can solve for a stack of 1 disc" $ do moves <- hanoiOf 1 -- a@[1] b@[] c@[] moves `shouldBe` [ Move "a" "c" -- a@[] b@[] c@[1] ] it "can solve for a stack of 2 discs" $ do moves <- hanoiOf 2 -- a@[1, 2] b@[] c@[] moves `shouldBe` [ Move "a" "c", -- a@[2] b@[] c@[1] Move "a" "b", -- a@[] b@[2] c@[1] Move "c" "a", -- a@[1] b@[2] c@[] Move "a" "c", -- a@[1] b@[] c@[2] Move "a" "c" -- a@[] b@[] c@[1, 2] ] it "can solve for a stack of 3 discs" $ do moves <- hanoiOf 3 -- a@[1, 2, 3] b@[] c@[] moves `shouldBe` [ Move "a" "c", -- a@[2, 3] b@[] c@[1] Move "a" "b", -- a@[3] b@[2] c@[1] Move "c" "b", -- a@[3] b@[1, 2] c@[] Move "a" "c", -- a@[] b@[1, 2] c@[3] Move "b" "a", -- a@[1] b@[2] c@[3] Move "b" "c", -- a@[1] b@[] c@[2, 3] Move "a" "c" -- a@[] b@[] c@[1, 2, 3] ] {----------------------------------------------------------------------------} {- MOVE ---------------------------------------------------------------------} {----------------------------------------------------------------------------} -- Testing individual moves describe "move" $ do it "moves the smallest peg from peg A to peg C if peg C's disc is bigger" $ do let pegs = Pegs { pegsList = [ Peg {pegLabel = "a", pegDiscs = [Disc 1, Disc 3]}, Peg {pegLabel = "b", pegDiscs = []}, Peg {pegLabel = "c", pegDiscs = [Disc 2]} ], pegsMoves = [] } -- run the function (moveMade, pegsAfterMove) <- runPegs move pegs -- a move should have been made moveMade `shouldBe` Just (Move "a" "c") -- the pegs should have changed pegsList pegsAfterMove `shouldBe` [ Peg {pegLabel = "a", pegDiscs = [Disc 3]}, Peg {pegLabel = "b", pegDiscs = []}, Peg {pegLabel = "c", pegDiscs = [Disc 1, Disc 2]} ] {----------------------------------------------------------------------------} {- PEGS ---------------------------------------------------------------------} {----------------------------------------------------------------------------} -- Testing constructor for a set of pegs describe "initPegs" $ do it "creates pegs with labels and fills the first peg with discs" $ do pegs <- initPegs ["a", "b", "c"] 3 pegs `shouldBe` Pegs { pegsList = [ Peg {pegLabel = "a", pegDiscs = [Disc 1, Disc 2, Disc 3]}, Peg {pegLabel = "b", pegDiscs = []}, Peg {pegLabel = "c", pegDiscs = []} ], pegsMoves = [] } {----------------------------------------------------------------------------} {- PEG ----------------------------------------------------------------------} {----------------------------------------------------------------------------} -- Testing constructor for a peg with discs describe "fillPeg" $ do it "creates a list of disks from biggest to smallest" $ do fillPeg "a" 3 `shouldBe` Peg { pegLabel = "a", pegDiscs = [Disc 1, Disc 2, Disc 3] } -- Testing constructor for a peg without discs describe "emptyPeg" $ do it "creates an empty peg" $ do emptyPeg "a" `shouldBe` Peg { pegLabel = "a", pegDiscs = [] } -- Testing constructor for a stack of discs describe "stackDiscs" $ do it "should create a stack of discs from smallest to largest" $ do stackDiscs 3 `shouldBe` [Disc 1, Disc 2, Disc 3]