Skip to content

Instantly share code, notes, and snippets.

@nickjj

nickjj/codes.ex Secret

Created July 5, 2019 10:27
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nickjj/99ea84f460f41dae4139d0610ce8030c to your computer and use it in GitHub Desktop.
Save nickjj/99ea84f460f41dae4139d0610ce8030c to your computer and use it in GitHub Desktop.
# Original 730ms version to generate 5,000 random codes.
defmodule V1 do
def random_code() do
charset = "CDEFGHJKLMNPQRTUVWXYZ23679" |> String.split("", trim: true)
random_chars = Enum.reduce((0..16), [], fn (_i, acc) ->
[Enum.random(charset) | acc]
end) |> Enum.join("")
group_a = String.slice(random_chars, 1..4)
group_b = String.slice(random_chars, 5..8)
group_c = String.slice(random_chars, 9..12)
group_d = String.slice(random_chars, 13..16)
"#{group_a}-#{group_b}-#{group_c}-#{group_d}"
end
end
# 25ms version to generate 5,000 random codes.
defmodule V7 do
chars = 'CDEFGHJKLMNPQRTUVWXYZ23679'
@char_count length(chars)
for {char, i} <- Enum.with_index(chars, 1) do
def char(unquote(i)), do: unquote(char)
end
def generate() do
<<
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
?-,
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
?-,
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
?-,
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count)),
char(:rand.uniform(@char_count))
>>
end
end
# 3ms version to generate 5,000 random codes.
defmodule V4 do
chars = 'CDEFGHJKLMNPQRTUVWXYZ23679CDEFGHJKL'
@chars List.to_tuple(chars)
def encode(data, charset) do
# Maps the data to the charset
encode(data, charset, [])
end
def encode(<<>>, _, acc) do
acc
end
def encode(
<<a::size(5), b::size(5), c::size(5), d::size(5), e::size(5), f::size(5), g::size(5),
h::size(5), a2::size(5), b2::size(5), c2::size(5), d2::size(5), e2::size(5),
f2::size(5), g2::size(5), h2::size(5), rest::binary>>,
charset,
acc
) do
encode(rest, charset, [
IO.iodata_to_binary([
elem(@chars, a),
elem(@chars, b),
elem(@chars, c),
elem(@chars, d),
'-',
elem(@chars, e),
elem(@chars, f),
elem(@chars, g),
elem(@chars, h),
'-',
elem(@chars, a2),
elem(@chars, b2),
elem(@chars, c2),
elem(@chars, d2),
'-',
elem(@chars, e2),
elem(@chars, f2),
elem(@chars, g2),
elem(@chars, h2)
])
| acc
])
end
def generate(n) do
# We need n codes
# Each code is 16 bytes from charset
# Each byte needs 5 bits of random data
# So the number of bytes needed is
# n * 16 / 8 * 5 = n * 2 * 5 = n * 10
:crypto.strong_rand_bytes(n * 10)
|> encode(@chars)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment