Some of these might work

main
trivernis 10 months ago
parent 2db6211c58
commit a33ff440d0
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -3,7 +3,7 @@ set shell := ["nu", "-c"]
default:
print "Select a command"
dev target +FLAGS="": (build target FLAGS)
dev target +FLAGS="--dev": (build target FLAGS)
if ('out/{{target}}' | path exists) { out/{{target}} } else { ^$"out/('{{target}}' | str replace -r '\.roc$' '')" }
build target +FLAGS="--optimize": init

@ -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
)

@ -6,14 +6,18 @@ app "prime"
main : Task.Task {} I32
main =
numStrings =
List.range { start: At 0u64, end: At 1_000_000u64 }
|> List.map \e -> isPrimePre e
|> List.walk [] primeWalk
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
@ -36,23 +40,49 @@ isPrimePre = \n ->
No n
else if n < 4 then
Yes n
else if (firstPrimes |> List.any \p -> n > p && n % p == 0) then
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.toF64 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.toF64 valLimit
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 -> n % p == 0
|> List.any \p -> Num.isMultipleOf n p
|> Bool.not
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]
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)

@ -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…
Cancel
Save