与えた条件を満たす候補
Posted feedbacks - Haskell
こんな感じ。 *Main> f ["and","or","not","and"] (True,True,True,True) (True,True,False,True) (True,False,False,True) (False,True,False,True) (False,False,False,True)
1 2 3 4 5 6 7 8 9 10 | t :: (Bool -> Bool) -> [Bool] -> [String] -> Bool
t prev (x:[]) _ = prev x
t prev (x:xs) (op:ops) | op == "not" = t prev (not x:xs) ops
| op == "and" = t ((&&) (prev x)) xs ops
| op == "or" = t ((||) (prev x)) xs ops
f :: [String] -> IO ()
f ops = mapM_ print [(b1,b2,b3,b4) | bs@(b1:b2:b3:[b4]) <- bss, test bs ops]
where bss = sequence $ replicate 4 [True,False]
test = t id
|
Main> f ["and","or","not","and"] [True,True,True,True] [True,True,False,True] [False,True,False,True] [True,False,False,True] [False,False,False,True] 解を直接構成。"and"を100個並べて入力してもすぐ終わる(もちろん"or"だと無理です)。
1 2 3 4 5 6 | f = mapM_ (print . reverse) . g . reverse
g [] = [[True]]
g ("not":ops) = [not b:bs | (b:bs)<-g ops]
g ("and":ops) = map (True:) (g ops)
g ("or":ops) = map (False:) (g ops) ++ map (True:) anybs
where anybs = sequence $ (replicate.length.head.g) ops [True,False]
|
guard をつかってみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import Control.Monad
starling f g x = f x (g x)
f :: [String] -> [[Bool]]
f cs = sequence (replicate 4 [False,True])
>>= starling ((>>) . guard . flip (t id) cs) return
t :: (Bool -> Bool) -> [Bool] -> [String] -> Bool
t prev [x] _ = prev x
t prev (x:xs) ("not":ops) = t prev (not x:xs) ops
t prev (x:xs) ("and":ops) = t (prev x &&) xs ops
t prev (x:xs) ("or" :ops) = t (prev x ||) xs ops
{-
*Main> f ["and","or","not","and"]
[[False,False,False,True]
,[False,True,False,True]
,[True,False,False,True]
,[True,True,False,True]
,[True,True,True,True]]
-}
|
関数型っぽいですね。 foldl を使って写経。(test の部分のみ)
1 2 3 4 5 6 | test xs ops = p x where
(p, x:_) = foldl f (id, xs) ops
f (prev, x:xs) op
| op == "not" = (prev, not x:xs)
| op == "and" = (((&&) (prev x)), xs)
| op == "or" = (((||) (prev x)), xs)
|
効率良さそうですね。 foldl を使って写経。
1 2 3 4 | f = mapM_ (print . reverse) . snd . foldl g (1, [[True]]) where
g (l,bs) "not" = (l, [not b:bs' | (b:bs')<-bs])
g (l,bs) "and" = (l+1, map (True:) bs)
g (l,bs) "or" = (l+1, map (False:) bs ++ sequence ([True]: replicate l [True,False]))
|





にしお
#3399()
Rating0/0=0.00
元ネタの 充足可能性問題 - Wikipedia は、 同じリテラル(x1とかnot x2とか)が複数回出てくることを想定しているので、 今回の問題のようにそれぞれ別の変数でだと乗法標準形 - Wikipediaにした場合に、答えが…と色々悩みどころでした。
[ reply ]