|
|
|
app "prime2"
|
|
|
|
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
|
|
|
|
imports [pf.Stdout, pf.Task, pf.Arg]
|
|
|
|
provides [main] to pf
|
|
|
|
|
|
|
|
main : Task.Task {} I32
|
|
|
|
main =
|
|
|
|
max <- Task.await parseArg
|
|
|
|
numStrings =
|
|
|
|
primesIn max
|
|
|
|
|> List.map Num.toStr
|
|
|
|
|> Str.joinWith "\n"
|
|
|
|
|
|
|
|
Stdout.line "$(numStrings)"
|
|
|
|
|
|
|
|
parseArg =
|
|
|
|
args <- Task.await (Arg.list)
|
|
|
|
arg =
|
|
|
|
args
|
|
|
|
|> List.get 1
|
|
|
|
|> Result.withDefault "50_000_000"
|
|
|
|
|> Str.toU64
|
|
|
|
when arg is
|
|
|
|
Ok a -> a |> Task.ok
|
|
|
|
Err InvalidNumStr -> crash "Passed argument is not a numberr"
|
|
|
|
|
|
|
|
primesIn : U64 -> List U64
|
|
|
|
primesIn = \n ->
|
|
|
|
numbers = List.concat [2] (List.range { start: At 3u64, end: At n, step: 2 })
|
|
|
|
primeSieve numbers n
|
|
|
|
|
|
|
|
primeSieve : List U64, U64 -> List U64
|
|
|
|
primeSieve = \l, max ->
|
|
|
|
when l is
|
|
|
|
[] -> []
|
|
|
|
[a] -> [a]
|
|
|
|
[head, ..] if (Num.powInt head 2) > max -> l
|
|
|
|
[head, .. as tail] ->
|
|
|
|
filteredList = List.dropIf tail (\e -> Num.isMultipleOf e head)
|
|
|
|
List.concat [head] (primeSieve filteredList max)
|
|
|
|
|
|
|
|
countPrimesIn : U64 -> Nat
|
|
|
|
countPrimesIn = \limit ->
|
|
|
|
List.range { start: At 2, end: At limit }
|
|
|
|
|> List.countIf \n ->
|
|
|
|
if n < 4 then
|
|
|
|
Bool.true
|
|
|
|
else if Num.isEven n 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 100000
|
|
|
|
|> \expected ->
|
|
|
|
dbg expected
|
|
|
|
|
|
|
|
expected
|
|
|
|
)
|
|
|
|
== (
|
|
|
|
List.len (primesIn 100000)
|
|
|
|
|> \actual ->
|
|
|
|
dbg actual
|
|
|
|
|
|
|
|
actual
|
|
|
|
|
|
|
|
)
|