Skip to content

@jed /LICENSE.txt forked from 140bytes/LICENSE.txt
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
generate random UUIDs

UUID

Returns a random v4 UUID of the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where each x is replaced with a random hexadecimal digit from 0 to f, and y is replaced with a random hexadecimal digit from 8 to b.

There's also @LeverOne's approach using iteration, which is one byte shorter.

function b(
a // placeholder
){
return a // if the placeholder was passed, return
? ( // a random number from 0 to 15
a ^ // unless b is 8,
Math.random() // in which case
* 16 // a random number from
>> a/4 // 8 to 11
).toString(16) // in hexadecimal
: ( // or otherwise a concatenated string:
[1e7] + // 10000000 +
-1e3 + // -1000 +
-4e3 + // -4000 +
-8e3 + // -80000000 +
-1e11 // -100000000000,
).replace( // replacing
/[018]/g, // zeroes, ones, and eights with
b // random hex digits
)
}
function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Jed Schmidt <http://jed.is>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "UUID",
"description": "Generates random UUIDs",
"keywords": [
"UUID",
"ID",
"random"
]
}
@subzey

We can use coercion and exponential notation to get template string and save 7 bytes:
function(){return(""+1e7+-1e3+-4e3+-8e3+-1e11).replace(/1|0/g,function(){return(0|Math.random()*16).toString(16)})}

@jed
Owner

subzey, you are a genius. fixing and annotating now.

@jed
Owner

you also inspired me to cut 10 more bytes out:

function b(a){return a?(0|Math.random()*16).toString(16):(""+1e7+-1e3+-4e3+-8e3+-1e11).replace(/1|0/g,b)}
@jed
Owner
(0|Math.random()*16).toString(16)

can also be trimmed 4 bytes to

Math.random().toString(16)[2]

if you don't care about IE... thoughts?

@subzey

@jed, Math.random() may return 0, so Math.random().toString(16)[2] may return undefined.

Also, isn't setting name of function affects the outer scope?

@jed
Owner

well, with the chance of Math.random returning a zero 1 in 2<<61, seems like the definition of an edge case. more likely that IE barfs on it.

also, we're allowing named functions because we assume that they'll be assigned externally.

@subzey

@jed, thanks for your clarification about function names, I didn't know that

@jed
Owner

@subzey, i hope you use this knowledge to bring us some awesome new stuff.

@LeverOne

""+1e7+-1e3+-4e3+-8e3+-1e11 --> [1e7]+-1e3+-4e3+-8e3+-1e11
it's а flaw of many of you.

@subzey

@LeverOne, perfect! Thanks

@jed
Owner
jed commented

wow, that's crazy. good work @LeverOne.

@fgnass

What about replacing /1|0/ with /\d/?

@jed
Owner
jed commented

the 4 is hardcoded according to the spec, and the 8 is a bit of a hack... technically it should be anything from 8 to b. so replacing those would make it less compliant.

@fgnass

Ah I see, I missed that.

@jed
Owner
jed commented

i wonder if we finally have enough bytes to make it compliant, such that the 8 can be 8, 9, a, or b...

@subzey

It is enough already :)

function c(a,b){return a?(~~b+0|Math.random()*16>>b/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/1|0|(8)/g,c)}
@subzey

Or this, shorter:

function c(a,b){return a?(b|Math.random()*16>>b/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/1|0|(8)/g,c)}
@jed
Owner
jed commented

thanks again, @subzey. updated.

@broofa

Line 20 of annotated.js should be 'c', not 'b'.

BTW, you're all insane. I love it! :)

@jed
Owner
jed commented

good catch! for those not in the know, @broofa is a celebrity in the world of UUIDs: https://github.com/broofa/node-uuid

@tsaniel

Maybe save 4 bytes...?
```function c(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[108]/g,c)}

@jed
Owner
jed commented

what the... how on earth does this work?

@tsaniel

There are three possible values 0,1,8 for a.

For case 0: 0^Math.random()*16>>0/4, >>0/4 is actually >>0, just works as Math.floor.
The 0^ here does nothing.

For case 1: 1^Math.random()*16>>1/4, >>1/4 is still >>0.
Although 1^ here toggles the least significant bit, we can still use it to generate random numbers 0-15.

For case 8: 8^Math.random()*16>>8/4, >>8/4 turns out >>2.
The maximum number of Math.random()*16 in binary form is 1111, that means the range is 0000-1111.
By right shifting 2 bits, the maximum number of Math.random()*16>>2 is 0011, and the range, 0000-0011. What it does here is to generate random numbers 0-3.
Finally, because the most significant bit is always 0, 8^ is actually 8|, it is to ensure the range starts from 8. And now we get 8 + {0, 1, 2, 3}.

@jed
Owner
jed commented

incredible work, @tsaniel!

@jed
Owner
jed commented

it's amazing how this gist has evolved, from

function(){return"00000000-0000-4000-8000-000000000000".replace(/0/g,function(){return(0|Math.random()*16).toString(16)})}

to

function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}

while hitting all the greatest hits: recursion, coercion of a number into a string through an array (!), operator repurposing...

@tsaniel

I love those tricks, especially the string coercion with array, though i love bitwise tricks.
By the way, i am still thinking if we can shorten /[018]/...

@atk
atk commented

@tsaniel - no way, the other way round would be /[^4-]/, which is just as long.

@tsaniel

@atk: That's true. I mean if we can do something to use /\d/ instead.

@atk
atk commented

...which would require that the 4 will be left alone and enlarge the equation probably more than the 3 letters we saved.

@tsaniel

Maybe that's the end.

@atk
atk commented

I fear it is.

@subzey

Once again, excellent work, @tsaniel!

Sorry for my late comment, my mobile browser doesn't work well with github

@LeverOne

Recursion & coercion vs. loop & math: https://gist.github.com/1308368

@jed
Owner

just when you thought it couldn't get any shorter, @LeverOne sheds a byte. good job!

@tsaniel

@LeverOne is my hero.

@kalupa

damnit jed, i keep finding you everywhere. thanks for this!

@jussi-kalliokoski

In Firefox you could use the single statement function body to shorten it a few bits still:

function b(a)a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)
@jussi-kalliokoski

Shorter yet (cheats, ES6, and works only in Firefox!!!), and less leaky:

function()([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,a=>(a^Math.random()*16>>a/4).toString(16))
@jussi-kalliokoski

Hah, since I already used ES6 and there are no variable assignments, might as well go all the way and avoid Firefox-only stuff:

()=>([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,a=>(a^Math.random()*16>>a/4).toString(16))
@jameswyse

This is awesome!

Here's a benchmark vs node-uuid: http://jsperf.com/node-uuid-performance/11

@ronkorving

I was so rooting for Crazy Gist to win that one :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.