しりとり

30分プログラム、その55。

http://www.agusa.i.is.nagoya-u.ac.jp/person/mzp/hiki/?exerciseより。

与えられた単語を全て1回ずつ使い、しりとりができるかどうか判定するプログラムを書け。

*Main> siritori ["ABC","CBC","CDC"]
[["ABC","CBC","CDC"],["ABC","CDC","CBC"]]
*Main> siritori ["elvis","eve","alice","spaid"]
[["alice","eve","elvis","spaid"]]
import Control.Monad
connect :: String -> String -> Bool
connect xs (y:ys) = (last xs) == y
 
startFrom :: String->[String]->[[String]]
startFrom start [x] 
    | connect start x = [[x]]
    | otherwise       = []
startFrom start choices = do choice <- choices
                             guard $ connect start choice
                             follow <- startFrom choice 
                                                 [x | x<-choices , x /= choice]
                             return $ choice:follow
 
siritori :: [String]->[[String]]
siritori words = do word <- words
                    follow <- startFrom word [x | x <- words, x /=word]
                    return $ word:follow
  • 30分プログラム、Haskell
  • 死ぬほど大変だった。これをid:zyxwvはすらすら書きそうだから困る