cf. 今日の一行 – loopの列挙
trail
はすでにたどったノードのリスト p
と次にたどるノードの候補 q
を受け取って,全ての経路を列挙する。「次のノード」がスタートと同じならそこでそのループは終わり。違うなら再帰的にノードをたどる。
各ノードは比較さえできればいいので Eq a
にした。入出力の関係で結局は文字列になってるけど。
module Main (main) where
import Data.List (intersperse)
import System (getArgs)
trail :: (Eq a) => [a] -> [a] -> [[a]]
trail p q = concat $ map trail' q
where
trail' q1 | head p == q1 = [ p ++ [q1] ]
| otherwise = trail (p ++ [q1]) $ filter (q1/=) q
trailLoop :: (Eq a) => a -> [a] -> [[a]]
trailLoop s = trail [s]
enumLoops :: (Eq a) => [a] -> [[a]]
enumLoops nodes = concat $ map (flip trailLoop nodes) nodes
showLoop :: [String] -> String
showLoop = concat . intersperse " -> "
main :: IO ()
main = do nodes <- getArgs
mapM_ (putStrLn . showLoop) $ enumLoops nodes
実行例
D:\>runghc enumLoops.hs 1 2 3
1 -> 1
1 -> 2 -> 1
1 -> 2 -> 3 -> 1
1 -> 3 -> 1
1 -> 3 -> 2 -> 1
2 -> 1 -> 2
2 -> 1 -> 3 -> 2
2 -> 2
2 -> 3 -> 1 -> 2
2 -> 3 -> 2
3 -> 1 -> 2 -> 3
3 -> 1 -> 3
3 -> 2 -> 1 -> 3
3 -> 2 -> 3
3 -> 3
ノードが1つ増えるとループはぐっと増える。
D:\>runghc enumLoops.hs 1 2 3 4
1 -> 1
1 -> 2 -> 1
1 -> 2 -> 3 -> 1
1 -> 2 -> 3 -> 4 -> 1
1 -> 2 -> 4 -> 1
1 -> 2 -> 4 -> 3 -> 1
1 -> 3 -> 1
1 -> 3 -> 2 -> 1
1 -> 3 -> 2 -> 4 -> 1
1 -> 3 -> 4 -> 1
1 -> 3 -> 4 -> 2 -> 1
1 -> 4 -> 1
1 -> 4 -> 2 -> 1
1 -> 4 -> 2 -> 3 -> 1
1 -> 4 -> 3 -> 1
1 -> 4 -> 3 -> 2 -> 1
2 -> 1 -> 2
2 -> 1 -> 3 -> 2
2 -> 1 -> 3 -> 4 -> 2
2 -> 1 -> 4 -> 2
2 -> 1 -> 4 -> 3 -> 2
2 -> 2
2 -> 3 -> 1 -> 2
2 -> 3 -> 1 -> 4 -> 2
2 -> 3 -> 2
2 -> 3 -> 4 -> 1 -> 2
2 -> 3 -> 4 -> 2
2 -> 4 -> 1 -> 2
2 -> 4 -> 1 -> 3 -> 2
2 -> 4 -> 2
2 -> 4 -> 3 -> 1 -> 2
2 -> 4 -> 3 -> 2
3 -> 1 -> 2 -> 3
3 -> 1 -> 2 -> 4 -> 3
3 -> 1 -> 3
3 -> 1 -> 4 -> 2 -> 3
3 -> 1 -> 4 -> 3
3 -> 2 -> 1 -> 3
3 -> 2 -> 1 -> 4 -> 3
3 -> 2 -> 3
3 -> 2 -> 4 -> 1 -> 3
3 -> 2 -> 4 -> 3
3 -> 3
3 -> 4 -> 1 -> 2 -> 3
3 -> 4 -> 1 -> 3
3 -> 4 -> 2 -> 1 -> 3
3 -> 4 -> 2 -> 3
3 -> 4 -> 3
4 -> 1 -> 2 -> 3 -> 4
4 -> 1 -> 2 -> 4
4 -> 1 -> 3 -> 2 -> 4
4 -> 1 -> 3 -> 4
4 -> 1 -> 4
4 -> 2 -> 1 -> 3 -> 4
4 -> 2 -> 1 -> 4
4 -> 2 -> 3 -> 1 -> 4
4 -> 2 -> 3 -> 4
4 -> 2 -> 4
4 -> 3 -> 1 -> 2 -> 4
4 -> 3 -> 1 -> 4
4 -> 3 -> 2 -> 1 -> 4
4 -> 3 -> 2 -> 4
4 -> 3 -> 4
4 -> 4