stevensonmt

stevensonmt

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

Showing Posts 1 to 5

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

stevensonmt

stevensonmt OP

I guess I don’t understand the need to concat [3,5] but pass nil as the first round argument instead of just starting with [3,5] as the cached_primes? initial value.

stevensonmt

stevensonmt OP

Very nice work. Going to try a deeper dive into it to try and understand more fully. Thanks!

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.

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New

Other Trending Topics Top

mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews