require Sequences
defmodule SequencesTest do
def run do
IO.puts "Sequences.nats |> Enum.take(10)"
Sequences.nats |> Enum.take(10) |> IO.inspect
IO.puts "Sequences.fibs |> Enum.take(10)"
Sequences.fibs |> Enum.take(10) |> IO.inspect
IO.puts "Sequences.fibs |> Enum.at(99)"
Sequences.fibs |> Enum.at(99) |> IO.inspect
IO.puts "Sequences.primes |> Enum.take(20)"
Sequences.primes |> Enum.take(20) |> IO.inspect
IO.puts "Sequences.primes |> Enum.at(9999)"
Sequences.primes |> Enum.at(9999) |> IO.inspect
end
end
SequencesTest.run
defmodule Sequences do
@doc ~S"""
Natural Integers (Non-Negative Integers).
## Examples
# take 1..10
iex> Sequences.nats |> Enum.take(10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
"""
def nats do
&nats(1, &1, &2)
end
defp nats(_, {:halt, acc}, _fun), do: {:halted, acc}
defp nats(n, {:suspend, acc}, fun), do: {:suspended, acc, &nats(n, &1, fun)}
defp nats(n, {:cont, acc}, fun), do: nats(n + 1, fun.(n, acc), fun)
@doc ~S"""
Fibonacci Sequence ([1, 1, 2, 3, ...]).
## Examples
# take first 10 Fibonacci Numbers.
iex> Sequences.fibs |> Enum.take(10)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
# The 100th Fibonacci Number
iex> Sequences.fibs |> Enum.at(99)
354224848179261915075
"""
def fibs do
&fibs({1, 1}, &1, &2)
end
defp fibs(_, {:halt, acc}, _fun), do: {:halted, acc}
defp fibs(v, {:suspend, acc}, fun), do: {:suspended, acc, &fibs(v, &1, fun)}
defp fibs({a, b}, {:cont, acc}, fun), do: fibs({b, a + b}, fun.(a, acc), fun)
@doc ~S"""
Primes.
## Examples
# First 20 primes
iex> Sequences.primes |> Enum.take(20)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
# The 10000th prime
iex> Sequences.primes |> Enum.at(9999)
104729
"""
def primes do
&primes(2, &1, &2)
end
defp primes(_, {:halt, acc}, _fun), do: {:halted, acc}
defp primes(v, {:suspend, acc}, fun) do
{:suspended, acc, &primes(v, &1, fun)}
end
defp primes(2, {:cont, acc}, fun) do
primes(3, fun.(2, acc), fun)
end
defp primes(3, {:cont, acc}, fun) do
primes({%{}, 5, 2, nil}, fun.(3, acc), fun)
end
defp primes({h, p, d, nil}, {:cont, acc}, fun) do
m = next_m(h, p, p, 4, true)
n = p + d
next_h = h |> Map.put(m, p)
primes({next_h, n, 6 - d, Map.get(next_h, n)}, fun.(p, acc), fun)
end
defp primes({h, q, d, b}, {:cont, _} = acc, fun) do
k = if rem(q + b, 3) == 0, do: 2, else: 4
m = next_m(h, b, q, k, true)
n = q + d
next_h = h |> Map.put(m, b) |> Map.delete(q)
primes({next_h, n, 6 - d, Map.get(next_h, n)}, acc, fun)
end
defp next_m(_, _, m, _, false), do: m
defp next_m(h, n, pre_m, k, true) do
m = pre_m + n * k
next_m(h, n, m, 6 - k, Map.has_key?(h, m))
end
end