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