http://projecteuler.net/index.php?section=problems&id=38
nで左辺第1項の範囲が決まるので、あとはpandigitalになっているかチェックするだけ。
let rec pow n e = if e = 0 then 1 else n * (pow n (e - 1))
let rec digits n = if n = 0 then [] else (digits (n / 10)) @ [n % 10]
let to_number a = List.fold (fun x y -> x * 10 + y) 0 a
let rec is_pandigital ds flag =
if ds = [] then true
else
let d = List.head ds
if d = 0 then false
else
let f = 1 <<< d
if (flag &&& f) = 0 then
is_pandigital (List.tail ds) (flag ||| f)
else
false
let ceil n m = (n + m - 1) / m
let seq_pali n = seq {
let q = 9 / n
let r = 9 % n
let min_m = if r > 0 then ceil (pow 10 q) (n - r + 1)
else pow 10 (q - 1)
let max_m = if r > 0 then ((pow 10 (q + 1)) - 1) / (n - r)
else ((pow 10 q) - 1) / n
for m in min_m..max_m do
let a = List.concat (seq { for k in 1..n -> digits (k * m) })
if is_pandigital a 0 then
yield (to_number a)
}
printfn "%d" (Seq.max (seq { for n in 2..9 do
for m in seq_pali n -> m }))