oegma2
Why is my random number lookup slow using lists?
Hi, I am new to Elixir world and still have a long way to go, but starting with a basic problem I’ve been using to learn any new language - one with monkies hitting random keys and see if they can write a chapter out of Shakespeare’s book
- but in order to solve this problem, I need to generate a random letter, representing the monkey’s hitting a key…So after a bit of googling found an option using List and rand.uniform(…) to return a random “key” out of a fixed list
The problem is, doing this function over and over is a key component and is really slow compared to any other language… I know Elixir and the BEAM VM are designed for reliability and thus immutable obj can slow things down…
Is there any solution to speed this code up below, so that I can continue the journey with Elixir and write a program that can spawn million’s of monkies, all hitting keys
chars = ‘ABCDEFGHIJKLMNOPQRSTUVW’
data = List.to_tuple(chars)
for x <- 0…1000000 do
elem(data, :rand.uniform(22))
end
Most Liked
benwilson512
He wasn’t providing a faster solution, he was showing how the code underlying your existing solution worked, demonstrating that it was O(N).
Probably the fastest thing is to just compute a random number between 0 and 22 and add the correct ASCII offset.
random_char = [:random.uniform(22) + 65]
hauleth
Except I would write it as:
random_char = [:rand.uniform(?Z - ?A) + ?A)]
For less “magic numbers”. Also :rand is preferred solution over :random.
However I am not sure if Enum.random(?A..?Z) isn’t optimised for such case (and if not it probably would be nice addition).
EDIT:
Enum.random(?A..?Z) will run in constant time and space, so it would be the best and the fastest solution.
cc @oegma2
hauleth
Lists do not support random access and access is linear, so to get nth element you need n steps. In other words the Enum.at/2 for list will be implemented as:
def at([], _), do: nil
def at([val | rest], 0), do: val
def at([_ | rest], n) when n > 0, do: at(rest, n - 1)
rvirding
Yes, this is explicitly mentioned in the module rand docs:
The builtin random number generator algorithms are not cryptographically strong. If a cryptographically strong random number generator is needed, use something like crypto:rand_seed/0.
hauleth
For cryptographically secure rands you need to use :crypto.random_bytes/1, :rand isn’t crypto safe either.







