On Sun, Mar 07, 2004 at 04:49:39PM +0900, Charles Comstock wrote:
> >
> >No Enumerable#size.  Try:
> >
> >module Enumerable
> >    ## Return a random element, or nil if empty.
> >    def rand
> >        i = 1
> >        ret = nil
> >        each do |el|
> >            if Kernel.rand(i) == 0
> >                ret = el
> >            end
> >            i += 1
> >        end
> >        return ret
> >    end
> >end
> >
> >
> 
> Umm I don't think that is a uniform distribution, not to mention the 

It *is* uniform...

> fact that you don't break out of the each if it succeeds.

... precisely because he doesn't break out of the each if it succeeds.

S(i): element i is taken in ret = el (i.e. Kernel.rand(i) == 0)
AND: intersection
PI: big PI (product)
N: number of elements in the Enumerable (if infinite, rand would never
return)

P(ret == el(i) at the end) = P(S(i) AND (for all N >= j > i NOT S(j)))
== { they're independent if we ignore the fact that this is a PRNG } ==
= P(S(i)) * P(for all j > i NOT (S(j))) == { S(j) and S(j+1) indep. } ==
= 1/i * PI(1-P(S(j)), j = i+1 .. N) = 
= 1/i * (1-1/(i+1)) * (1-1/(i+2)) * ... * (1-1/(N)) =
= 1/i * i/(i+1) * (i+1)/(i+2) * ... * (N-1)/N = 
= 1/i * i / N = 1 / N


-- 
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Netscape is not a newsreader, and probably never shall be.
	-- Tom Christiansen