Skip to content

Instantly share code, notes, and snippets.

@03juan
Created August 6, 2021 11:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 03juan/45a17e4b395c779038e3dc32b79eae05 to your computer and use it in GitHub Desktop.
Save 03juan/45a17e4b395c779038e3dc32b79eae05 to your computer and use it in GitHub Desktop.
Simple generation of seeded, URL-safe strings

Simple generation of seeded, URL-safe strings

Module

Simplification of ahmadshah/randomizer.ex with seeded RNG.

defmodule Randomizer do
  # Generate the various lists at compile time for better performance and scalability
  @upcase Enum.to_list(?A..?Z)
  @downcase Enum.to_list(?a..?z)
  @alpha @upcase ++ @downcase
  @numeric Enum.to_list(?0..?9)
  @all @alpha ++ @numeric

  defp list(:upcase), do: @upcase
  defp list(:downcase), do: @downcase
  defp list(:alpha), do: @alpha
  defp list(:numeric), do: @numeric
  defp list(_), do: @all

  def randomize(length, seed, type \\ :all) do
    :rand.seed(:exsss, [seed])

    list = list(type)

    # When length == 1, Enum.to_list(1..1) == [1]
    1..length
    |> Enum.map(fn _ -> Enum.random(list) end)
    |> List.to_string()
  end
end

Tests

ExUnit.start()

defmodule RandomizerTest do
  use ExUnit.Case

  test "generate random string" do
    random = Randomizer.randomize(10, 123)
    assert 10 = String.length(random)
    assert String.match?(random, ~r/[A-Za-z0-9]/)
  end

  test "generate random numbers" do
    random = Randomizer.randomize(10, 123, :numeric)
    assert 10 = String.length(random)
    refute String.match?(random, ~r/[A-Za-z]/)
  end

  test "generate random upper case" do
    random = Randomizer.randomize(10, 123, :upcase)
    assert 10 = String.length(random)
    refute String.match?(random, ~r/[a-z0-9]/)
  end

  test "generate random lower case" do
    random = Randomizer.randomize(10, 123, :downcase)
    assert 10 = String.length(random)
    refute String.match?(random, ~r/[A-Z0-9]/)
  end

  test "generate random alphabets only" do
    random = Randomizer.randomize(10, 123, :alpha)
    assert 10 = String.length(random)
    refute String.match?(random, ~r/[0-9]/)
  end

  test "generate same output with same seed" do
    r1 = Randomizer.randomize(10, 123)
    r2 = Randomizer.randomize(10, 123)

    assert r1 == r2
  end

  test "generate different output with different seed" do
    r1 = Randomizer.randomize(10, 123)
    r2 = Randomizer.randomize(10, 124)

    refute r1 == r2
  end
end

ExUnit.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment