Yet Another Drop Function

Run Settings
LanguageElixir
Language Version
Run Command
require Sequences require Drop defmodule DropTest do def run do IO.puts "enum0 = Sequences.fibs |> Stream.map(&IO.inspect/1)" enum0 = Sequences.fibs |> Stream.map(&IO.inspect/1) IO.puts "enum1 = enum0 |> drop(5)" enum1 = enum0 |> Drop.drop(5) IO.puts "enum1 |> Enum.take(5) |> IO.inspect" enum1 |> Enum.take(5) |> IO.inspect IO.puts "enum1 |> Enum.at(5) |> IO.inspect" enum1 |> Enum.at(5) |> IO.inspect end end DropTest.run
defmodule Drop do @doc ~S""" Drop Function. Similar to `Stream.drop`, but STRICTLY drops first `n` elements (n > 0). ## Examples iex> Sequences.fibs |> Drop.drop(5) |> Enum.take(5) [8, 13, 21, 34, 55] """ def drop(enum, count) do fun = fn (v, 0) -> {:suspend, v} (_, n) -> {:cont, n - 1} end case Enumerable.reduce(enum, {:cont, count - 1}, fun) do {:halted, _} -> [] {:done, _} -> [] {:suspended, _, next_fun} -> &do_drop(next_fun, &1, &2) end end defp do_drop(_, {:halt, acc}, _fun), do: {:halted, acc} defp do_drop(next, {:suspend, acc}, fun) do {:suspended, acc, &do_drop(next, &1, fun)} end defp do_drop(next, {:cont, acc}, fun) do case next.({:cont, 0}) do {:halted, _} -> {:halted, acc} {:done, _} -> {:done, acc} {:suspended, v, next_fun} -> do_drop(next_fun, fun.(v, acc), fun) end end end
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
Editor Settings
Theme
Key bindings
Full width
Lines