bruteforce
問題の最初の有効な解決策を見つけるために遅延評価を使用して
、小さな関数を実装しました。
import Data.Maybe
bruteforce :: (a -> Bool) -> [a] -> Maybe a
bruteforce f xs
| null result = Nothing
| otherwise = Just $ head result
where
result = mapMaybe bruteforce' xs
-- test one instance
bruteforce' x
| f x = Just x
| otherwise = Nothing
generatorString :: Int -> [String]
generatorString 0 = [""]
generatorString deep = concatMap (\x -> map (\ys -> (x:ys)) nextgen) ['a'..'z']
where nextgen = generatorString (deep - 1)
main :: IO ()
main = do
putStrLn $ fromJust $ bruteforce ((==) "zabcde") (generatorString 6)
gist としても利用できます。はい、テスト関数はばかげていますが、何が問題なのかを示すには十分です。期待どおりに動作しますが、メモリ消費量が非常に多くなります。
$ ghc --make -O2 brute.hs -o brute -rtsopts
$ ./brute +RTS -s
zabcde
24,752,866,120 bytes allocated in the heap
15,748,430,224 bytes copied during GC
581,741,352 bytes maximum residency (22 sample(s))
18,464,056 bytes maximum slop
1719 MB total memory in use (0 MB lost due to fragmentation)
[...]
そこで、より少ないメモリを使用して RTS を強制しようとしました (つまり、GC をより頻繁に呼び出します)。200MBで十分ですか?
$ ./brute +RTS -s -M200M
Heap exhausted;
Current maximum heap size is 209715200 bytes (200 MB);
use `+RTS -M<size>' to increase it.
まあ、いいえ(とにかくこのアプローチは好きではありません...)
bruteforce
よりメモリに優しいように書き直す方法はありますか?