Ensuring random list of numbers are unique

Hey all, using ruby 1.8.7, I wrote this:

500.times.map { Integer((rand * 1) * 1000) / Float(1000) }

Basically, this gives me a list of 500 random decimal numbers that are
rounded to 3 places. However, I also want to make sure that all are
unique.

thanks for response

On Tue, Feb 28, 2012 at 7:10 PM, John M. [email protected] wrote:


You received this message because you are subscribed to the Google G. “Ruby
on Rails: Talk” group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.

Here is one thing that comes to mind

a = (1…1000).to_a
a.shuffle!

pick 1st 500
a[0,500]

last 500 item from the list
a[-500…-1]

If you want you can call shuffle a few times, see what works best for
you.


Kind Regards,
Rajinder Y.

SafetyNet Test Driven Development
http://safetynet.devmentor.org

500.times.map { Integer((rand * 1) * 1000) / Float(1000) }

Basically, this gives me a list of 500 random decimal numbers that are
rounded to 3 places. However, I also want to make sure that all are
unique.

Tack a .uniq to the end…

-philip

On Tue, Feb 28, 2012 at 8:03 PM, Valery K. [email protected] wrote:

.uniq() doesn’t guarentee 500 number exactly.

secure(500, 3)
=> collection of 500 unique random numbers.

Sweet!

On 29.02.2012, at 4:10, John M. wrote:

Hey all, using ruby 1.8.7, I wrote this:

500.times.map { Integer((rand * 1) * 1000) / Float(1000) }

Basically, this gives me a list of 500 random decimal numbers that are
rounded to 3 places. However, I also want to make sure that all are
unique.

.uniq() doesn’t guarentee 500 number exactly.
.shuffle() just tosses the collection and doesn’t give you unique
numbers.

You’d better to implement method:

def secure(number, precision)
collection = []
collection |= [SecureRandom.random_number.round(precision)] while
collection.size < number
collection
end

secure(500, 3)
=> collection of 500 unique random numbers.

Valery K. wrote in post #1049372:

You’d better to implement method:

def secure(number, precision)
collection = []
collection |= [SecureRandom.random_number.round(precision)] while
collection.size < number
collection
end

secure(500, 3)
=> collection of 500 unique random numbers.

One simple way to get what you want is by using a set:

Here’s your method of generating random numbers. Don’t count on it
giving you “secure” random numbers, but this technique won’t care how
you produced them.

#!/usr/bin/env ruby
require ‘set’

def random_numbers(n = 500)
my_set = Set.new
while my_set.size < 500
value = Integer((rand * 1) * 1000) / Float(1000)
my_set << value
end
my_set.to_a
end

puts random_numbers.size

Robert W. wrote in post #1049376:

#!/usr/bin/env ruby
require ‘set’

def random_numbers(n = 500)
my_set = Set.new
while my_set.size < 500
value = Integer((rand * 1) * 1000) / Float(1000)
my_set << value
end
my_set.to_a
end

puts random_numbers.size

One caveat with this technique: Make sure you build in some “circuit
breaker” protection code. The more numbers you ask this to generate the
more rounds it will take to produce the result. Generating 500 unique
numbers is averaging about 700 rounds. The closer to 1000 you get the
more rounds it will take. Over 1000 and it will never finish.

On 29 February 2012 00:10, John M. [email protected] wrote:

500.times.map { Integer((rand * 1) * 1000) / Float(1000) }

Basically, this gives me a list of 500 random decimal numbers that are
rounded to 3 places. However, I also want to make sure that all are
unique.

This is a classic “how do I achieve my solution?”, rather than a
“here’s my problem… how can I solve it” post…

Can we back up a second please?
What are you trying to achieve with this list of 500 numbers? And what
do you want to do if the list you have generated does contain
duplicates?
As already said, you can use the .uniq method to remove dupes - but
that might leave you with an array of 496 elements… would that be a
problem? Are you really asking “how do I generate an array of 500
random numbers”?

What do you want to do with these 500 random numbers? Considering that
one user could make a request and get their 500 randoms, and another
user could do the same - there could be duplicates across users. Is
this going to be a problem?

Please try to ask clearer questions, as the way it stands, I could
spend ages of my time coming up with solutions to what I think is
your problem, just to have you say “nope… that’s not what I was
after”. Multiply that across the subscribers to this list, and you’ve
wasted a hell of a lot of peoples’ time around the world :-/

PS BTW Why are you multiplying by 1 in your example code? (and does
that line even work if you paste it into your console, as it explodes
for me with a LocalJumpError… but that may just be Ruby versions…)

On Wed, Feb 29, 2012 at 3:05 AM, Robert W. [email protected]
wrote:

my_set.to_a
end

puts random_numbers.size

One caveat with this technique: Make sure you build in some “circuit
breaker” protection code. The more numbers you ask this to generate the
more rounds it will take to produce the result. Generating 500 unique
numbers is averaging about 700 rounds. The closer to 1000 you get the
more rounds it will take. Over 1000 and it will never finish.

Another caveat is that the Array contains “Float” objects, while the
original question was “500 unique decimals”. Two issues here:

  1. if “decimals” are asked in the problem statement, why then do
    we serve Floats in the result?

  2. The problem is that for uniqueness, we need the ‘==’ operator and
    on Floats that represent fractional numbers in the decimal system,
    equality is not a stable function (as was discussed many times before
    …).

So, in all proposed solutions, I would exchange this line:

value = Integer((rand * 1) * 1000) / Float(1000)

with this one:

  value = rand(1000) / BigDecimal.new(1000)

HTH,

Peter

On 1 March 2012 01:05, John M. [email protected] wrote:

thanks for responses, the ultimate goal was just to ensure a list of
500 (no more or less) unique random decimals that are 3 places which
would be generated only one time. Currently Im storing them as a float
in the mysql database.

One time for ever? You do realise there’s only 1000 numbers between 0
and 0.999?
After two runs, you’ll have used up the whole pool.

On Thu, Mar 1, 2012 at 2:05 AM, John M. [email protected] wrote:

thanks for responses, the ultimate goal was just to ensure a list of
500 (no more or less) unique random decimals that are 3 places which
would be generated only one time. Currently I’m storing them as a float
in the mysql database.

Do yourself a favor and change your migration with a line like this:

t.decimal :number, :precision => 10, :scale => 3

That’s all it takes to use decimals (with 3 digits following the decimal
point)
in the database too.

HTH,

Peter

thanks for responses, the ultimate goal was just to ensure a list of
500 (no more or less) unique random decimals that are 3 places which
would be generated only one time. Currently Im storing them as a float
in the mysql database.