Skip to content

Instantly share code, notes, and snippets.

@jeremybradbury
Last active January 9, 2022 09:23
Show Gist options
  • Save jeremybradbury/c3e1c63532558aed1e264e6dade012b4 to your computer and use it in GitHub Desktop.
Save jeremybradbury/c3e1c63532558aed1e264e6dade012b4 to your computer and use it in GitHub Desktop.
Six Digit Code generated by PostgreSQL on one line. Simple function too.
-- source oneliner - all caps letters + 10 digits - base 36 ~2.17B enums
SELECT array_to_string(array(select substr('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',((random()*(36-1)+1)::integer),1) from generate_series(1,6)),'') AS "Code";
/*
Code
--------
EY25QI
(1 row)
*/
-- function - skip O & I - base 34 ~1.5B enums
CREATE OR REPLACE FUNCTION six_digit_code RETURNS TEXT() AS $$
RETURN SELECT array_to_string(array(select substr('ABCDEFGHJKLMNPQRSTUVWXYZ0123456789',((random()*(34-1)+1)::integer),1) from generate_series(1,6)),'');
$$ LANGUAGE SQL;
-- results match oneliner
SELECT six_digit_code() AS "Code";
/*
Code
--------
1F2R0B
(1 row)
*/
@jeremybradbury
Copy link
Author

jeremybradbury commented Dec 16, 2021

Example output: Code: FTSZB2

Here are the total possible enumerations for base 36, up to 6 digits: 36^6 = 2,176,782,336

If we subtract all enumerations of 1-5 digits it's still quite large: (36^6) - (36^5) = 2,116,316,160

This creates only 6 digit choices, choosing a random "digit" (or base 36 char) each time, using generate_series(1,6), before we coerce it back into a string.

If this isn't for captcha, you can modify it to remove any 0/O, 1/I, 5/S or 8/B confusion without dipping below 1 Billion enumerations (at base 32).
Or you can make only those letters lowercase instead: 0/o, 1/i, 5/s or 8/b, but keep the rest upper or L will duplicate the problem etc.
I don't recommend symbol replacement as that's typically a UX nightmare.

You can also grow this to base 62 adding lower cases which makes the confusion problem worse, but there's base 58 which fixes the confusion issue (but not 5/S/s or 8/B), while using both upper/lower cases.

Perhaps something like base 54, missing 4 upper (B/I/O/S) & 4 lower case (i/l/o/s) letters (b & L are not a problem, but I, O & S are).

TLDR: remix until desired results emerge, prioritize keeping decimals over letters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment