-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patheuler-041.fs
62 lines (53 loc) · 2.54 KB
/
euler-041.fs
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#light
open System.Collections
let isPrimes N =
let sieve = new BitArray(int(N-1u))
sieve.SetAll(true);
let numberToIndex n = n-2u
let setFlag n value = sieve.Set(int(numberToIndex n), value)
let getFlag n = sieve.Get(int(numberToIndex n))
let checkComposites prime = for n in {2u*prime .. prime .. N} do false |> setFlag n
let rec tryfind_nextprime n =
if n > N then None elif getFlag n then Some n else tryfind_nextprime (n+1u)
let rec filterSieve i =
match i with
| Some(i) when i*i > N -> ()
| Some(i) -> checkComposites i;
i+1u |> tryfind_nextprime |> filterSieve
| None -> ()
filterSieve (Some 2u);
(fun n -> getFlag n)
let factorial N =
if N < 1 then 1I
else {1I .. bigint.FromInt32(N)} |> Seq.fold ( * ) 1I
let getLexicographicPermutationByIndex permutation index =
let rec getLexicographicPermutationByIndex_aux permEls i acc =
match permEls with
| [] -> acc
| p ->
let N = p |> List.length
let from1_NToPermElement n = {1..N} |> Seq.zip (p |> Seq.orderBy (fun a -> a)) |> Seq.find_index (fun v -> v=n)
let facN_1 = factorial (N-1)
let elOfPerm = bigint.ToInt32(bigint.FromInt32(i) / facN_1 + 1I) |> from1_NToPermElement
let newPermEls = p |> List.filter (fun v -> v <> elOfPerm)
let newi = bigint.ToInt32(bigint.FromInt32(i) % facN_1)
let newacc = acc @ [elOfPerm]
getLexicographicPermutationByIndex_aux newPermEls newi newacc
getLexicographicPermutationByIndex_aux permutation index []
let allDigits (v:int) = v.ToString() |> Seq.map (fun d -> int(d)-int('0'))
let digitsListToNumber l =
let (sum, pow10) = List.fold_right (fun iN (sum, pow10) -> (sum+iN*pow10,pow10*10)) l (0,1)
sum
//Note: Nine numbers cannot be done (1+2+3+4+5+6+7+8+9=45 => always dividable by 3)
//Note: Eight numbers cannot be done (1+2+3+4+5+6+7+8=36 => always dividable by 3)
let maxDigits = 7
let answer =
let d = {maxDigits .. -1 .. 1}
let isPrime = isPrimes (uint32(d |> Seq.to_list |> digitsListToNumber ))
d |> Seq.map (fun dlen ->
let total = bigint.ToInt32(factorial dlen)
{total-1 .. -1 .. 0} |> Seq.map (fun index ->
getLexicographicPermutationByIndex ({1..dlen} |> Seq.to_list) index)
) |> Seq.concat |> Seq.map (fun s -> digitsListToNumber s) |>
Seq.first (fun p -> if isPrime (uint32(p)) then Some(p) else None)
print_any answer