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 hanoiOf 1 -- a@[1] b@[] c@[] `shouldBe` Right [ Move "a" "c" -- a@[] b@[] c@[1] ] it "can solve for a stack of 2 discs" $ do hanoiOf 2 -- a@[2, 1] b@[] c@[] `shouldBe` Right [ 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@[2, 1] ] it "can solve for a stack of 3 discs" $ do hanoiOf 3 -- a@[3, 2, 1] b@[] c@[] `shouldBe` Right [ Move "a" "c", -- a@[3, 2] b@[] c@[1] Move "a" "b", -- a@[3] b@[2] c@[1] Move "c" "b", -- a@[3] b@[2, 1] c@[] Move "a" "c", -- a@[] b@[2, 1] c@[3] Move "b" "a", -- a@[1] b@[2] c@[3] Move "b" "c", -- a@[1] b@[] c@[3, 2] Move "a" "c" -- a@[] b@[] c@[3, 2, 1] ] {----------------------------------------------------------------------------} {- 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 emptyPegs = initPegs "a" "b" "c" 0 pegs = emptyPegs { pegsPegA = (emptyPeg "a") {pegDiscs = [Disc 3, Disc 1]}, pegsPegC = (emptyPeg "c") {pegDiscs = [Disc 2]} } -- run the function (moveMade, pegsAfterMove) = move pegs -- a move should have been made moveMade `shouldBe` Just (Move "a" "c") -- the pegs should have changed pegsAfterMove `shouldBe` pegs { pegsPegA = (pegsPegA pegs) {pegDiscs = [Disc 3]}, pegsPegC = (pegsPegC pegs) {pegDiscs = [Disc 2, Disc 1]} } {----------------------------------------------------------------------------} {- PEGS ---------------------------------------------------------------------} {----------------------------------------------------------------------------} -- Testing constructor for a set of pegs describe "initPegs" $ do it "creates pegs with labels and fills the first peg with discs" $ do initPegs "a" "b" "c" 3 `shouldBe` Pegs { pegsPegA = Peg {pegLabel = "a", pegDiscs = [Disc 3, Disc 2, Disc 1]}, pegsPegB = Peg {pegLabel = "b", pegDiscs = []}, pegsPegC = Peg {pegLabel = "c", pegDiscs = []} } {----------------------------------------------------------------------------} {- 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 3, Disc 2, Disc 1] } -- 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 largest to smallest" $ do stackDiscs 3 `shouldBe` [Disc 3, Disc 2, Disc 1]