RosettaCodeData/Task/Extensible-prime-generator/Elixir/extensible-prime-generator.ex

64 lines
2.1 KiB
Elixir

defmodule PrimesSoEMap do
@typep stt :: {integer, integer, integer, Enumerable.integer, %{integer => integer}}
@spec advance(stt) :: stt
defp advance {n, bp, q, bps?, map} do
bps = if bps? === nil do Stream.drop(oddprms(), 1) else bps? end
nn = n + 2
if nn >= q do
inc = bp + bp
nbps = bps |> Stream.drop(1)
[nbp] = nbps |> Enum.take(1)
advance {nn, nbp, nbp * nbp, nbps, map |> Map.put(nn + inc, inc)}
else if Map.has_key?(map, nn) do
{inc, rmap} = Map.pop(map, nn)
[next] =
Stream.iterate(nn + inc, &(&1 + inc))
|> Stream.drop_while(&(Map.has_key?(rmap, &1))) |> Enum.take(1)
advance {nn, bp, q, bps, Map.put(rmap, next, inc)}
else
{nn, bp, q, bps, map}
end end
end
@spec oddprms() :: Enumerable.integer
defp oddprms do # put first base prime cull seq in Map so never empty
# advance base odd primes to 5 when initialized
init = {7, 5, 25, nil, %{9 => 6}}
[3, 5] # to avoid race, preseed with the first 2 elements...
|> Stream.concat(
Stream.iterate(init, &(advance &1))
|> Stream.map(fn {p,_,_,_,_} -> p end))
end
@spec primes() :: Enumerable.integer
def primes do
Stream.concat([2], oddprms())
end
end
IO.write "The first 20 primes are:\n( "
PrimesSoEMap.primes() |> Stream.take(20) |> Enum.each(&(IO.write "#{&1} "))
IO.puts ")"
IO.write "The primes between 100 to 150 are:\n( "
PrimesSoEMap.primes() |> Stream.drop_while(&(&1<100))
|> Stream.take_while(&(&1<150)) |> Enum.each(&(IO.write "#{&1} "))
IO.puts ")"
IO.write "The number of primes between 7700 and 8000 is: "
PrimesSoEMap.primes() |> Stream.drop_while(&(&1<7700))
|> Stream.take_while(&(&1<8000)) |> Enum.count |> IO.puts
IO.write "The 10,000th prime is: "
PrimesSoEMap.primes() |> Stream.drop(9999)
|> Enum.take(1) |> List.first |>IO.puts
IO.write "The sum of all the priems to two million is: "
testfunc =
fn () ->
ans =
PrimesSoEMap.primes() |> Stream.take_while(&(&1<=2000000))
|> Enum.sum() |> IO.puts
ans end
:timer.tc(testfunc)
|> (fn {t,_} ->
IO.puts "This test bench took #{t} microseconds." end).()