You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.3 KiB
Plaintext

app "prime"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
imports [pf.Stdout, pf.Task]
provides [main] to pf
main : Task.Task {} I32
main =
numStrings =
primesIn 50_000_000
|> List.map Num.toStr
|> Str.joinWith "\n"
Stdout.line "$(numStrings)"
primesIn : U64 -> List U64
primesIn = \n ->
List.range { start: At 0u64, end: At n }
|> List.map \e -> isPrimePre e
|> List.walk [] primeWalk
PrimeResult : [No U64, Yes U64, Maybe U64]
primeWalk : List U64, PrimeResult -> List U64
primeWalk = \l, n ->
when n is
Yes n2 ->
List.append l n2
Maybe n2 ->
if isPrimePost l n2 then
List.append l n2
else
l
No _ -> l
isPrimePre : U64 -> PrimeResult
isPrimePre = \n ->
if n < 2 then
No n
else if n < 4 then
Yes n
else if Num.isEven n then
No n
else if
(
firstPrimes
|> List.dropIf \p -> n < p
|> List.any \p -> Num.isMultipleOf n p
)
then
No n
else
Maybe n
firstPrimes =
[2, 3, 5, 7, 9, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 51, 67, 71, 73, 79, 83, 89, 97]
isPrimePost : List U64, U64 -> Bool
isPrimePost = \l, n ->
nFloat = Num.toF32 n
valLimit = Num.ceiling (Num.sqrt nFloat)
# approximate the number of primes < sqrt(n) to limit the range we have to check with a 25% error tolerance
valLimitF = Num.toF32 valLimit
limit = Num.ceiling (valLimitF * 1.25 / (Num.log valLimitF))
l
|> List.sublist { start: 0, len: limit }
|> List.dropIf \p -> p > valLimit
|> List.any \p -> Num.isMultipleOf n p
|> Bool.not
countPrimesIn : U64 -> Nat
countPrimesIn = \limit ->
List.range { start: At 2, end: At limit }
|> List.countIf \n ->
if n < 4 then
Bool.true
else if n % 2 == 0 then
Bool.false
else
res =
List.range { start: At 3, end: At (Num.ceiling (Num.sqrt (Num.toF64 n))), step: 2 }
|> List.any \a -> Num.isMultipleOf n a
|> Bool.not
res
expect countPrimesIn 10000 == List.len (primesIn 10000)