Some of these might work
parent
2db6211c58
commit
a33ff440d0
@ -0,0 +1,122 @@
|
||||
app "prime-bin-search"
|
||||
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 500_000
|
||||
|> List.map Num.toStr
|
||||
|> Str.joinWith "\n"
|
||||
|
||||
Stdout.line "$(numStrings)"
|
||||
|
||||
primesIn : U64 -> List U64
|
||||
primesIn = \n ->
|
||||
numbers = List.range { start: At 2u64, end: At n }
|
||||
List.walk numbers numbers primeWalk
|
||||
|
||||
primeWalk : List U64, U64 -> List U64
|
||||
primeWalk = \l, n ->
|
||||
if l |> binarySearchContains n then
|
||||
if n > 1 then
|
||||
l
|
||||
|> List.dropIf \e ->
|
||||
e > n && Num.isMultipleOf e n
|
||||
else
|
||||
l
|
||||
else
|
||||
l
|
||||
|
||||
binarySearchContains : List U64, U64 -> Bool where a implements Eq
|
||||
binarySearchContains = \l, a ->
|
||||
len = List.len l
|
||||
|
||||
if Num.isZero len then
|
||||
Bool.false
|
||||
else
|
||||
half = Num.shiftRightBy len 1
|
||||
binarySearchContainsRec l a half half
|
||||
|
||||
binarySearchContainsRec : List U64, U64, Nat, Nat -> Bool where a implements Eq
|
||||
binarySearchContainsRec = \l, n, mid, step ->
|
||||
if step <= 1 then
|
||||
sublist = List.sublist l { start: (mid - (Num.min step mid)), len: (step * 2 + 1) }
|
||||
|
||||
when sublist is
|
||||
[] -> Bool.false
|
||||
[a] -> n == a
|
||||
[a, b] -> n == a || n == b
|
||||
[a, b, c] -> n == a || n == b || n == c
|
||||
_ -> crash "This shoulnd't have happened"
|
||||
else
|
||||
element = List.get l mid |> Result.withDefault 0
|
||||
|
||||
when Num.compare n element is
|
||||
EQ -> Bool.true
|
||||
ne ->
|
||||
newStep = Num.divCeil step 2
|
||||
len = l |> List.len
|
||||
|
||||
when ne is
|
||||
GT if mid >= len -> Bool.false
|
||||
GT -> binarySearchContainsRec l n (mid + newStep) newStep
|
||||
LT if mid < newStep -> binarySearchContainsRec l n 0 newStep
|
||||
LT -> binarySearchContainsRec l n (mid - newStep) newStep
|
||||
_ -> crash "This shoulnd't have happened"
|
||||
|
||||
orderedContains : List (Num a), Num a -> Bool where a implements Eq
|
||||
orderedContains = \l, a ->
|
||||
when l |> List.findFirst \e -> e >= a is
|
||||
Err NotFound -> Bool.false
|
||||
Ok f -> f == a
|
||||
|
||||
expect orderedContains [0, 1, 2, 3, 4, 5, 6] 5 == Bool.true
|
||||
expect binarySearchContains [0, 1, 2, 3, 4, 5, 6] 5 == Bool.true
|
||||
expect binarySearchContains [0, 1, 3, 4, 5, 6] 2 == Bool.false
|
||||
expect binarySearchContains [0, 1, 3, 4, 5, 6] 7 == Bool.false
|
||||
expect binarySearchContains [] 7 == Bool.false
|
||||
expect binarySearchContains [2] 2 == Bool.true
|
||||
expect binarySearchContains [1, 2, 3] 3 == Bool.true
|
||||
expect binarySearchContains [1, 2, 3] 1 == Bool.true
|
||||
expect binarySearchContains [1, 2, 3, 4, 5, 6] 0 == Bool.false
|
||||
|
||||
expect binarySearchContains (List.range { start: At 0, end: At 100000 }) 4 == Bool.true
|
||||
expect binarySearchContains (List.range { start: At 0, end: At 100000 } |> List.dropIf Num.isEven) 4 == Bool.false
|
||||
expect binarySearchContains (List.range { start: At 0, end: At 100000 } |> List.dropIf Num.isOdd) 97 == Bool.false
|
||||
expect binarySearchContains (List.range { start: At 0, end: At 100000 }) 99998 == Bool.true
|
||||
expect binarySearchContains (List.range { start: At 0, end: At 100000 }) 100001 == Bool.false
|
||||
|
||||
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 100000
|
||||
|> \expected ->
|
||||
dbg expected
|
||||
|
||||
expected
|
||||
)
|
||||
== (
|
||||
List.len (primesIn 100000)
|
||||
|> \actual ->
|
||||
dbg actual
|
||||
|
||||
actual
|
||||
|
||||
)
|
@ -0,0 +1,61 @@
|
||||
app "prime2"
|
||||
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 ->
|
||||
numbers = List.concat [2] (List.range { start: At 3u64, end: At n, step: 2 })
|
||||
primeSieve numbers
|
||||
|
||||
primeSieve : List U64 -> List U64
|
||||
primeSieve = \l ->
|
||||
when l is
|
||||
[] -> []
|
||||
[a] -> [a]
|
||||
[head, .., tail] if (Num.powInt head 2) > tail -> l
|
||||
[head, .. as tail] ->
|
||||
filteredList = List.dropIf tail (\e -> Num.isMultipleOf e head)
|
||||
List.concat [head] (primeSieve filteredList)
|
||||
|
||||
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
|
||||
|
||||
)
|
@ -0,0 +1,93 @@
|
||||
app "prime2"
|
||||
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 0, end: At n }
|
||||
|> List.map Yes
|
||||
|> primeSieve 0 n
|
||||
|> List.keepIf isYes
|
||||
|> List.map extractValueUnsafe
|
||||
|
||||
PrimeResult : [No, Yes U64]
|
||||
|
||||
primeSieve : List PrimeResult, U64, U64 -> List PrimeResult U64
|
||||
primeSieve = \l, idx, max ->
|
||||
len = List.len l
|
||||
when nextPrime l idx is
|
||||
Ok p if (Num.powInt p 2) > max -> l
|
||||
Ok p ->
|
||||
setNo l (List.range { start: At (Num.toNat (p * 2)), step: Num.toNat p, end: At len })
|
||||
|> primeSieve (idx + 1) max
|
||||
|
||||
Err _ -> l
|
||||
|
||||
isYes : PrimeResult -> Bool
|
||||
isYes = \r ->
|
||||
when r is
|
||||
No -> Bool.false
|
||||
Yes _ -> Bool.true
|
||||
|
||||
setNo : List PrimeResult, List Nat -> List PrimeResult U64
|
||||
setNo = \l, idxs ->
|
||||
when idxs is
|
||||
[] -> l
|
||||
[idx] -> l |> List.set idx No
|
||||
[head, .. as tail] -> l |> List.set head No |> setNo tail
|
||||
|
||||
nextPrime : List PrimeResult, U64 -> Result U64 [NotFound]
|
||||
nextPrime = \l, startIdx ->
|
||||
l
|
||||
|> List.dropFirst (Num.toNat (startIdx + 1))
|
||||
|> List.findFirst isYes
|
||||
|> Result.map extractValueUnsafe
|
||||
|
||||
extractValueUnsafe : PrimeResult -> U64
|
||||
extractValueUnsafe = \res ->
|
||||
when res is
|
||||
Yes n -> n
|
||||
No -> crash "No value found"
|
||||
|
||||
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
|
||||
|
||||
)
|
Loading…
Reference in New Issue