stevensonmt

stevensonmt

Prime sieve explanation

I tried to modify an example from RosettaCode.org for a prime sieve algorithm. I’m not entirely sure I understood the original code. I tried to make sense of it with more explicit variable names but I was hoping someone could correct my understanding if I missed something. Also wondering why you have to prepopulate the odd primes with 3 and 5.

  def primes_to(limit) do
    # prepopulate with 2 so we only have to check odd numbers
    [2]
    |> Stream.concat(oddprimes())
    |> Enum.take_while(&(&1 < limit))
  end

  defp oddprimes() do
    # prepopulating with 3 and 5 is necessary but not sure why
    [3, 5]
    |> Stream.concat(
      Stream.iterate(
        {5, 25, 7, nil, %{9 => 6}},
        &check_next(&1)
      )
      |> Stream.map(fn {_, _, p, _, _} -> p end)
    )
  end

  # map ==> %{next_next_odd => increment}
  defp check_next({last_prime, last_prm_sq, next_odd, cached_primes?, map}) do
    cached_primes =
      if cached_primes? === nil do
        oddprimes() |> Stream.drop(1)
      else
        cached_primes?
      end

    next_next_odd = next_odd + 2

    # if the next number to check would be greater than the square of the last prime
    # advance the next known prime and its square as the new minimum step
    if next_next_odd >= last_prm_sq do
      inc = last_prime + last_prime
      next_cached_primes = cached_primes |> Stream.drop(1)
      [next_last_prime] = next_cached_primes |> Enum.take(1)

      check_next(
        {next_last_prime, next_last_prime * next_last_prime, next_next_odd, next_cached_primes,
         map |> Map.put(next_next_odd + inc, inc)}
      )
    else
      # if the next number to check is under the minimum step to advance
      # check if the map includes that number and remove it
      # find the first multiple of the increment for that number that is not
      # in the map and put it in the rmap (produced by removing the next number)
      #  with the increment as the value and check the next odd with the current
      #  last prime limits and cache
      if Map.has_key?(map, next_next_odd) do
        {inc, rmap} = Map.pop(map, next_next_odd)

        [next_candidate] =
          Stream.iterate(next_next_odd + inc, &(&1 + inc))
          |> Stream.drop_while(&Map.has_key?(rmap, &1))
          |> Enum.take(1)

        check_next(
          {last_prime, last_prm_sq, next_next_odd, cached_primes,
           Map.put(rmap, next_candidate, inc)}
        )
      else
        # if the next number to check is under the minimum step to advance
        # and it is not a key in the current map check the next odd
        # against the current last prime limits, cache, and map of increments
        {last_prime, last_prm_sq, next_next_odd, cached_primes, map}
      end
    end
  end
end

Most Liked

al2o3cr

al2o3cr

The initial value of cached_primes? is an infinite stream, the first two elements of which happen to be 3 and 5 - the rest of it is the result of iterating check_next.

al2o3cr

al2o3cr

check_next uses oddprimes - which depends on check_next after the first two elements. The initial [3, 5] is similar to the “base case” in traditional recursive code; without it, the algorithm wouldn’t be able to get started.

the_wildgoose

the_wildgoose

Here’s my contribution to this… Priority queues turn out to be your next step up from the basic wheel for immutable languages. Perhaps it’s useful?

https://github.com/ewildgoose/elixir-primes

Where Next?

Popular in Questions Top

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New

Other popular topics Top

New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement