I found the
Deadbeef Random Number Generator when reading the
Reddit thread “What’s the best / most interesting piece of code you’ve ever seen?” – and since I’m trying to learn
F#, I figured I could try implementing it, first in an “imperative” way, then in a more functional way.
First the imperative way, a kind of naïve translation of the C code presented:
1 2 3 4 5 6 7 8 9 10 11 12 13
| let mutable (deadbeef_seed:uint32) = uint32 0;
let mutable (deadbeef_beef:uint32) = uint32 0xdeadbeef;
let deadbeef_srand x =
let oldseed = deadbeef_seed
deadbeef_seed <- x
deadbeef_beef <- uint32 0xdeadbeef
oldseed
let deadbeef_rand () =
deadbeef_seed <- (deadbeef_seed <<< 7) ^^^ ((deadbeef_seed >>> 25) + deadbeef_beef);
deadbeef_beef <- (deadbeef_beef <<< 7) ^^^ ((deadbeef_beef >>> 25) + (uint32 0xdeadbeef));
deadbeef_seed; |
This is not very functional, with mutables and all that, so I tried again, with an implementation requiring no mutable variables:
1 2 3 4 5 6 7 8 9
| let deadbeef_rand_seq seed = seq {
let rec db_rand seed beef = seq {
let newseed = (seed <<< 7) ^^^ ((seed >>> 25) + beef);
let newbeef = (beef <<< 7) ^^^ ((beef >>> 25) + (uint32 0xdeadbeef));
yield newseed
yield! db_rand newseed newbeef
}
yield! db_rand seed (uint32 0xdeadbeef)
} |
…much better (at least in my opinion); implemented as a sequence of random numbers, deadbeef_rand_seq(seed).Take(10) would give you 10 random uint32s.
I’ll bet there are about 1000 other ways to make this more F#-like/more functional, so I’d love to hear about them!
Recent Comments