Skip to content
This repository was archived by the owner on Sep 22, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions lib/orangeade/generator/atom.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
defmodule Orangeade.Generator.Atom do
@moduledoc """
Provides a function for creating a stream of ascii atoms.
"""

alias Orangeade.Generator.PrintableASCIIAlphabetCharacter.Minuscule
alias Orangeade.Generator.BoundNatural

@doc """
Creates a stream of ascii atoms of max default length 6.

## Examples

iex> Caffeine.Stream.take(
...> Orangeade.Generator.Atom.stream(),
...> 10)
[:seg, :icrifx, :v, :voya, :kxv, :enoxal, :new, :xidtdo, :ibmwc, :pemdfx]

"""
@spec stream() :: Caffeine.Stream.t()
def stream do
stream(max_word_length: 6)
end

@doc """
Given a max word length creates a stream of ascii atoms.

## Examples

iex> Caffeine.Stream.take(
...> Orangeade.Generator.Atom.stream(max_word_length: 10),
...> 10)
[:oyavicrif, :oxalkxvv, :wen, :done, :mwcxidt, :mdfxib, :yuepe, :yvgcbweioh,
:qdyvvut, :hs]

"""
@spec stream(max_word_length: non_neg_integer) :: Caffeine.Stream.t()
def stream(max_word_length: l) do
alphabet = Minuscule.stream()
lengths = BoundNatural.stream(limit: l)
stream(alphabet, lengths)
end

defp stream(alphabet, lengths) do
{word, atail} = split(alphabet, Caffeine.Stream.head(lengths))
rest = fn ->
stream(atail, Caffeine.Stream.tail(lengths)) end
Caffeine.Stream.construct(word, rest)
end

defp split(alphabet, length) do
split([], length + 1, alphabet)
end

defp split(word, 0, alphabet) do
{List.to_atom(word), alphabet}
end

defp split(word, n, alphabet) do
split([Caffeine.Stream.head(alphabet)|word], n - 1, Caffeine.Stream.tail(alphabet))
end

end
118 changes: 118 additions & 0 deletions lib/orangeade/generator/printable_ascii_alphabet_character.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
defmodule Orangeade.Generator.PrintableASCIIAlphabetCharacter do
@moduledoc """
Provides a function for creating a stream of ASCII alphabet characters.
"""
alias Caffeine.Stream
alias Orangeade.Generator.BoundNatural
alias Orangeade.Generator.PrintableASCIIAlphabetCharacter.Majuscule
alias Orangeade.Generator.PrintableASCIIAlphabetCharacter.Minuscule

defmodule Majuscule do
@doc """
Creates a stream of ASCII alphabet lowercase characters

# Example

iex> Caffeine.Stream.take(
...> Orangeade.Generator.PrintableASCIIAlphabetCharacter.Majuscule.stream(),
...> 50)
'XONEWENODTDIXCWMBIXFDMEPEUYHOIEWBCGVYTUVVYDQSHEMLB'

"""
@spec stream() :: Caffeine.Stream.t()
def stream do
Caffeine.Stream.map(BoundNatural.stream(limit: length()), &to_majuscule/1)
end

defp to_majuscule(n) do
n + lower_bound()
end

defp length do
upper_bound() - lower_bound()
end

def lower_bound do
?A
end

defp upper_bound do
?Z
end
end

defmodule Minuscule do
@doc """
Creates a stream of ASCII alphabet lowercase characters

# Example
iex> Caffeine.Stream.take(
...> Orangeade.Generator.PrintableASCIIAlphabetCharacter.Minuscule.stream(),
...> 50)
'onewenodtdixcwmbixfdmepeuyhoiewbcgvytuvvydqshemlbn'


"""
@spec stream() :: Caffeine.Stream.t()
def stream do
Caffeine.Stream.map(BoundNatural.stream(limit: length()), &to_minuscule/1)
end

defp to_minuscule(n) do
n + lower_bound()
end

def length do
upper_bound() - lower_bound()
end

def lower_bound do
?a
end

defp upper_bound do
?z
end
end

@doc """
Creates a stream of ASCII alphabet characters

# Example
iex> Caffeine.Stream.take(
...> Orangeade.Generator.PrintableASCIIAlphabetCharacter.stream(),
...> 50)
'NeWeNoDtDiXcWmBiXfDmEpEuYhOiEwBcGvYtUvVyDqShEmLbNc'


"""

@spec stream() :: Caffeine.Stream.t()
def stream do
base = BoundNatural.stream(limit: length())
filter = BoundNatural.stream(limit: 2)
stream(base, filter)
end

defp stream(base, filter) do
head = to_alphabet_character(Stream.head(base), Stream.head(filter))
rest = fn -> stream(Stream.tail(base),Stream.tail(filter)) end
Caffeine.Stream.construct(head, rest)
end

defp to_alphabet_character(base, filter) do
case filter do
1 ->
base + Majuscule.lower_bound()
0 ->
base + Minuscule.lower_bound()
end
end

defp length do
Minuscule.length()
end



end
21 changes: 21 additions & 0 deletions test/orangeade/generator/atom_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule Orangeade.Generator.AtomTest do
use ExUnit.Case

test "Check if first 10 generated elements are atoms" do
list_of_elements =
Orangeade.Generator.Atom.stream()
|> Caffeine.Stream.take(10)

assert Enum.all?(list_of_elements, &is_atom/1)
end

test "Check if atoms have default max word length not greater than 6" do
lengths_of_elements =
Orangeade.Generator.Atom.stream()
|> Caffeine.Stream.take(10)
|> Enum.map(&Atom.to_charlist/1)
|> Enum.map(&length/1)

refute Enum.any?(lengths_of_elements,fn e -> e > 6 end)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Orangeade.Generator.PrintableASCIIAlphabetCharacterTest do
use ExUnit.Case

test "Stream contains only alphabet characters" do
list = Orangeade.Generator.PrintableASCIIAlphabetCharacter.stream()
|> Caffeine.Stream.take(1_000)

refute Enum.any?(list, fn e ->
e < ?A or (e > ?Z and e < ?a) or e > ?z end)
end

test "Majuscule stream contains only uppercase characters" do
{min, max} = Orangeade.Generator.PrintableASCIIAlphabetCharacter.Majuscule.stream()
|> Caffeine.Stream.take(1_000)
|> Enum.min_max

assert (?A <= min) and (max <= ?Z)
end


test "Minuscule stream contains only lowercase characters" do
{min, max} = Orangeade.Generator.PrintableASCIIAlphabetCharacter.Minuscule.stream()
|> Caffeine.Stream.take(1_000)
|> Enum.min_max

assert (?a <= min) and (max <= ?z)
end

end
2 changes: 1 addition & 1 deletion test/orangeade/generator/term_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Orangeade.Generator.TermTest do
test "Check if there are different data types in first 100 generated elements" do
list_of_elements =
Term.stream()
|> Caffeine.Stream.take(100)
|> Caffeine.Stream.take(200)

list_of_conditions = [
Enum.any?(list_of_elements, &is_negative/1),
Expand Down