http://projecteuler.net/index.php?section=problems&id=47
素数関係のコードをいちいち書いたりコピペするのが面倒なので、別ファイルにします。そのときに、名前空間とモジュールを使います。
// mod1.fs namespace NS1 module Mod1 = let a = 1
// mod2.fs namespace NS1 module Mod2 = let b = 2
名前空間の中でモジュールを定義し、その中で定数や関数を定義します。
これをそれぞれコンパイルします。
>fsc mod1.fs --target:library
>fsc mod2.fs --target:library
そうすると、mod1.dllとmod2.dllが生成されます。
これらを利用したコードを書きます。
// test1.fs printfn "%d" NS1.Mod1.a // 1 printfn "%d" NS1.Mod2.b // 2
これを次のようにコンパイルします。
>fsc test1.fs -r:mod1.dll -r:mod2.dll
test1.exeが生成されます。
open Arithmetic let count n = Seq.initInfinite ((+) n) let num_facts = seq { for n in count 2 -> List.length (Primes.factorize n) } let N = 4 let s = seq { let counter = ref 0 for n, m in Seq.zip (count 2) num_facts do if m = N then counter := !counter + 1 if !counter = N then yield n - N + 1 else counter := 0 } printfn "%d" (Seq.head s)
namespace Arithmetic module Primes = let count n = Seq.initInfinite ((+) n) let rec calc_exp n p = if n % p = 0 then let t = calc_exp (n / p) p (fst t + 1, snd t) else (0, n) // prime numbers let is_prime n = let rec is_prime_core n k = let p = if k > 1 then k * 3 - (k &&& 1) - 1 else k + 2 if p * p > n then true else if n % p = 0 then false else is_prime_core n (k + 1) is_prime_core n 0 let sieve max_n = let a = Array.create (max_n + 1) true for p in Seq.takeWhile (fun p -> p * p <= max_n) (Seq.filter (fun n -> a.[n]) (count 2)) do for k in seq { p*2..p..max_n } do a.[k] <- false a let make_primes max_n = let a = sieve max_n Seq.toList (Seq.filter (fun n -> a.[n]) (seq { 2..max_n })) // factorization let rec fac n k = let p = if k > 1 then k * 3 - (k &&& 1) - 1 else k + 2 if n = 1 then [] else if p * p > n then [(n, 1)] else let t = calc_exp n p if fst t > 0 then (p, fst t) :: (fac (snd t) (k + 1)) else fac n (k + 1) let rec pow n e = if e = 0 then 1 else let m = pow n (e / 2) if e % 2 = 1 then m * m * n else m * m let factorize n = fac n 0 let value f = List.fold (fun x y -> x * (pow (fst y) (snd y))) 1 f let rec div_f f g = if f = [] then [] else if g = [] then f else let f0 = List.head f let g0 = List.head g if fst f0 = fst g0 then if snd f0 = snd g0 then div_f (List.tail f) (List.tail g) else (fst f0, (snd f0) - (snd g0)) :: (div_f (List.tail f) (List.tail g)) else div_f (List.tail f) g // divisor let rec divisors = function | [] -> [[]] | (p,e)::fs -> [ for t in (divisors fs) do for e' in [0..e] -> if e' = 0 then t else (p, e')::t ] let divs n = divisors (factorize n)