-- solves the problem using a BFS
solveBFS :: State -> Int
solveBFS state = let
        -- expands the state, filters out already visited states
        -- returns the number of moves needed to reach the final state
        step :: S.Seq (State, Int) -> HS.HashSet State -> Int
        step q found
            | stateIsFinal s = d
            | otherwise = let
                    states = S.filter (not . flip HS.member found) $ expandState s
                in
                    step
                        (qs S.>< fmap (\x -> (x, d + 1)) states)
                        (foldl (flip HS.insert) found states)
            where ((s, d), qs) = (S.index q 0, S.drop 1 q)
    in
        step (S.singleton (state, 0)) (HS.singleton state)
solveBFS :: State -> Int
solveBFS state = let
        -- expands the state, filters out already visited states
        -- returns the number of moves needed to reach the final state
        step :: S.Seq (State, Int) -> HS.HashSet State -> Int
        step q found
            | stateIsFinal s = d
            | otherwise = let
                    states = S.filter (not . flip HS.member found) $ expandState s
                in
                    step
                        (qs S.>< fmap (\x -> (x, d + 1)) states)
                        (foldl (flip HS.insert) found states)
            where ((s, d), qs) = (S.index q 0, S.drop 1 q)
    in
        step (S.singleton (state, 0)) (HS.singleton state)
solveBFS state = let
        -- expands the state, filters out already visited states
        -- returns the number of moves needed to reach the final state
        step :: S.Seq (State, Int) -> HS.HashSet State -> Int
        step q found
            | stateIsFinal s = d
            | otherwise = let
                    states = S.filter (not . flip HS.member found) $ expandState s
                in
                    step
                        (qs S.>< fmap (\x -> (x, d + 1)) states)
                        (foldl (flip HS.insert) found states)
            where ((s, d), qs) = (S.index q 0, S.drop 1 q)
    in
        step (S.singleton (state, 0)) (HS.singleton state)