X-Git-Url: https://code.kerkeslager.com/?p=sandbox;a=blobdiff_plain;f=elixir_primes%2Flib%2Fprimes.ex;fp=elixir_primes%2Flib%2Fprimes.ex;h=cab7035b21b00e69629f440157445b849666b756;hp=0000000000000000000000000000000000000000;hb=cee981b9b40676534e8ff6b690ac7f4b2c2064c8;hpb=84ed7dbc7fb20d2646f6783b4ed91a8e653092eb diff --git a/elixir_primes/lib/primes.ex b/elixir_primes/lib/primes.ex new file mode 100644 index 0000000..cab7035 --- /dev/null +++ b/elixir_primes/lib/primes.ex @@ -0,0 +1,58 @@ +defmodule SieveFilter do + def less_than?({a, _}, {b, _}) when a < b do true end + def less_than?({a, b}, {a, c}) when b < c do true end + def less_than?(_, _) do false end + + def get_next({counter, prime}) do {counter + prime, prime} end +end + +defmodule Sieve do + def run_item_through_sieve([{item, prime}|remaining_sieve], item) do + {matched, unmatched} = run_item_through_sieve(remaining_sieve, item) + {[{item, prime}|matched], unmatched} + end + def run_item_through_sieve(sieve, _) do {[], sieve} end + + def merge(xs, []) do xs end + def merge([], ys) do ys end + def merge(xs, ys) do + [x|remaining_xs] = xs + [y|remaining_ys] = ys + + if SieveFilter.less_than?(x, y) do + [x|merge(remaining_xs, ys)] + else + [y|merge(xs, remaining_ys)] + end + end + + def get_next(sieve) do + Enum.map(sieve, &(SieveFilter.get_next(&1))) + end +end + +defmodule Primes do + def transform(sieve, previous_item) do + item = previous_item + 1 + {matched, unmatched} = Sieve.run_item_through_sieve(sieve, item) + + case matched do + [] -> {Sieve.merge([{item * 2, item}], sieve), item} + _ -> transform(Sieve.merge(Sieve.get_next(matched), unmatched), item) + end + end + + def generate(initial_state, initial_item, get_next) do + Stream.map( + Stream.iterate( + {initial_state, initial_item}, + fn({previous_state, previous_item}) -> get_next.(previous_state, previous_item) end + ), + fn({_, item}) -> item end + ) + end + + def primes() do + Stream.drop(generate([], 1, &(transform(&1, &2))), 1) + end +end