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