昨日の虫食い算
昨日の虫食い算[id:dachs_hippo:20080315]をHaskellで書いてみました.
{- mushikui.hs -} import List f::[Int]->[Int]->[[String]] f ns = concat . map (\y -> (map (\x->[show x, show y, show $ x*y ]) ns)) g::[Int]->[Int] -> [([String],String)] g ns = (map (\x -> (x, sort $ concat x))) . (f ns) h::[Int] -> [Int] -> [String] h ns = (map (result.fst)) . (filter (fulldigit.snd) ) . (g ns) fulldigit::String -> Bool fulldigit "0123456789" = True fulldigit _ = False result::[String]->String result xs = ((xs!!0) ++ " * " ++ (xs!!1) ++ " = " ++ (xs!!2))
とにかく,ghciで実行.
___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Prelude> :l mushikui.hs [1 of 1] Compiling Main ( mushikui.hs, interpreted ) *Main> mapM_ putStrLn $ h [1000..9999] [2..9] 5694 * 3 = 17082 6819 * 3 = 20457 6918 * 3 = 20754 8169 * 3 = 24507 9168 * 3 = 27504 3907 * 4 = 15628 7039 * 4 = 28156 9127 * 4 = 36508 5817 * 6 = 34902 3094 * 7 = 21658 4093 * 7 = 28651 9304 * 7 = 65128 9403 * 7 = 65821
けど,美しくない.中間処理だけの関数が多いし,無駄に大きいリストを作ってる気がします(実際は遅延評価のおかげで作ってないのかもしれませんが).最初に[1000..9999] x [2..9]の値を全部計算して,それを最後の方まで引きずってるのが嫌です.先に一覧を作っておいて,それから必要なものを取り出すという流れは自然だと思うのですが,それならば一覧を作りながら必要なものだけを載せればよいのです.
{- mushikui2.hs -} import List f::[Int]->[Int]->[[Int]] f ns = (filter digitcheck) . concat . (map (\y -> (map (\x-> [x, y, x*y]) ns))) digitcheck::[Int] -> Bool digitcheck = fulldigit . sort . concat . (map show) fulldigit::String -> Bool fulldigit "0123456789" = True fulldigit _ = False result::[Int]->String result xs = (show(xs!!0) ++ " * " ++ show(xs!!1) ++ " = " ++ show(xs!!2))
実行してみます.
___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Prelude> :l mushikui.hs [1 of 1] Compiling Main ( mushikui2.hs, interpreted ) *Main> mapM_ (putStrLn.result) $ f [1000..9999] [2..9] 5694 * 3 = 17082 6819 * 3 = 20457 6918 * 3 = 20754 8169 * 3 = 24507 9168 * 3 = 27504 3907 * 4 = 15628 7039 * 4 = 28156 9127 * 4 = 36508 5817 * 6 = 34902 3094 * 7 = 21658 4093 * 7 = 28651 9304 * 7 = 65128 9403 * 7 = 65821
体感は大差ないから多分実際には大きな一覧はできてないんじゃないかとは思いますが,ま,ちょっとだけ綺麗になった気がするのでよしとします.
(追記)2008/3/39
リスト内包表記で書けばmapの二段重ねはいらないですね