正しい文(クイズ)
Posted feedbacks - Haskell
ナイーブな総当たりを書いてみましたが、n進数のnが増えると計算量が爆発しますね。あと、解は常に有限個だと思うんですが (ある点以上になると数字の数を増やすには数値の「桁を増やす」しかなくなるが、一桁増やしても数字そのものは1つしか増えないのに、その数値分の数字を確保するにはさらにおよそn個の数字が増えなければならない)、具体的な上限を求めるまでには至りませんでした。コードは無限に順列を生成してチェックしつづけるので実行時に適当にinterruptしてます。どうも3進以上は「1が11個」の解がmaxっぽい?
2進
この文は0が11個, 1が100個あります。
3進
この文は0が10個, 1が10個, 2が2個あります。
この文は0が2個, 1が2個, 2が10個あります。
この文は0が1個, 1が11個, 2が2個あります。
4進
この文は0が1個, 1が2個, 2が3個, 3が2個あります。
この文は0が1個, 1が3個, 2が1個, 3が3個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個あります。
5進
この文は0が1個, 1が3個, 2が2個, 3が3個, 4が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個あります。
6進
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個あります。
7進
この文は0が1個, 1が4個, 2が3個, 3が2個, 4が2個, 5が1個, 6が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個, 6が1個あります。
8進
この文は0が1個, 1が5個, 2が3個, 3が2個, 4が1個, 5が2個, 6が1個, 7が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個, 6が1個, 7が1個あります。
2進
この文は0が11個, 1が100個あります。
3進
この文は0が10個, 1が10個, 2が2個あります。
この文は0が2個, 1が2個, 2が10個あります。
この文は0が1個, 1が11個, 2が2個あります。
4進
この文は0が1個, 1が2個, 2が3個, 3が2個あります。
この文は0が1個, 1が3個, 2が1個, 3が3個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個あります。
5進
この文は0が1個, 1が3個, 2が2個, 3が3個, 4が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個あります。
6進
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個あります。
7進
この文は0が1個, 1が4個, 2が3個, 3が2個, 4が2個, 5が1個, 6が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個, 6が1個あります。
8進
この文は0が1個, 1が5個, 2が3個, 3が2個, 4が1個, 5が2個, 6が1個, 7が1個あります。
この文は0が1個, 1が11個, 2が2個, 3が1個, 4が1個, 5が1個, 6が1個, 7が1個あります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | module Main where
import Numeric
import Char
import System
import qualified System.IO.UTF8 as U
count pred [] = 0
count pred (x:xs) = (if pred x then 1 else 0) + count pred xs
countDigs radix k = let s = map digitToInt $ showIntAtBase radix intToDigit k $ ""
in map (\i -> count (==i) s) [0..(radix-1)]
countDigs' radix ks = foldl (\rs cs -> map (uncurry (+)) $ zip rs cs)
(replicate radix 0)
$ map (countDigs radix) ks
combListsM 1 lim = [[lim]]
combListsM n lim = [x:xs | x <- [1..(lim-1)], xs <- combListsM (n-1) lim]
++ [lim:xs | xs <- combListsS (n-1) lim]
++ [lim:xs | xs <- combListsM (n-1) lim]
combListsS 1 lim = [[x] | x <- [1..(lim-1)]]
combListsS n lim = [x:xs | x <- [1..(lim-1)], xs <- combListsS (n-1) lim]
combLists' n lim = combListsM n lim ++ combLists' n (lim+1)
combLists'' n = combLists' n 1
check radix (xs:xss) = let xs' = reverse xs
cs = map (+1) $ countDigs' radix xs'
in if and $ map (uncurry (==)) $ zip xs' cs
then xs':(check radix xss)
else check radix xss
solve radix = check radix $ combLists'' radix
showResult radix xs = (foldl ct "この文は" [0..(radix-1)]) ++ "あります。"
where ct cs i = cs ++ (if i == 0 then "" else ", ")
++ show i ++ "が"
++ showIntAtBase radix intToDigit (xs!!i) "個"
main = do args <- getArgs
case args of
[radix] -> case readDec radix of
(r,_):_ -> U.putStr
$ unlines
$ map (showResult r)
$ solve r
_ -> putStrLn "Usage: solve <radix>"
|
高階関数を使って。 書き換えた部分のみ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import List
import Maybe
count pred xs = length $ filter pred xs
countDigs' radix ks = map sum $ transpose $ map (countDigs radix) ks
combListsS n lim = sequence $ replicate n [1..lim-1]
combLists'' n = [1..] >>= combListsM n
check radix xss = mapMaybe f xss where
f xs = if xs' == cs then Just xs' else Nothing where
xs' = reverse xs
cs = map (+1) $ countDigs' radix xs'
showResult radix xs = ("この文は" ++) $ (++ "あります。")
$ concat $ intersperse ", "
$ map ct [0..radix-1]
where ct i = show i ++ "が" ++ showIntAtBase radix intToDigit (xs!!i) "個"
|





herumi
#4100()
Rating4/14=0.29
[ reply ]