Skip to content

Instantly share code, notes, and snippets.

@sebastien-p
Forked from 140bytes/LICENSE.txt
Created August 25, 2011 13:00
Show Gist options
  • Select an option

  • Save sebastien-p/1170594 to your computer and use it in GitHub Desktop.

Select an option

Save sebastien-p/1170594 to your computer and use it in GitHub Desktop.
base62 decode

140byt.es

A tweet-sized, fork-to-play, community-curated collection of JavaScript.

How to play

  1. Click the Fork button above to fork this gist.
  2. Modify all the files to according to the rules below.
  3. Save your entry and tweet it up!

Keep in mind that thanks to the awesome sensibilities of the GitHub team, gists are just repos. So feel free to clone yours and work locally for a more comfortable environment, and to allow commit messages.

Rules

All entries must exist in an index.js file, whose contents are

  1. a valid Javascript function expression, that
  2. optionally self-executes,
  3. contains no more than 140 bytes, and
  4. does not pollute global scope.

All entries must also be licensed under the MIT license.

For more information

The 140byt.es site hasn't launched yet, but for now follow @140bytes on Twitter.

To learn about byte-saving hacks for your own code, or to contribute what you've learned, head to the wiki.

140byt.es is brought to you by Jed Schmidt. It was inspired by work from Thomas Fuchs and Dustin Diaz.

function(){
/* Rules:
(1) anonymous function // make sure
(2) may be self-executing // to annotate
(3) <=140 bytes // your code
(4) no globals // so everyone
(5) MIT license // can learn
(6) have a good time! // from it!
*/}
function(){/*Rules: (1) anonymous function (2) may be self-executing (3) <=140 bytes (4) no globals (5) MIT license (6) have a good time!*/}
Copyright (c) 2011 YOUR_NAME_HERE, YOUR_URL_HERE
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
// [REQUIRED] A name for your library.
// This must match /^[a-z_]\w*$/i
"name": "140bytes",
// [OPTIONAL] A description of your library, phrased as a verb predicate.
// The gist description is used by default.
"description": "Explain the 140byt.es rules.",
// [OPTIONAL] Up to 5 keywords used for indexing.
"keywords": [
"140bytes",
"master",
"rules"
]
}
@atk
Copy link

atk commented Aug 25, 2011

A less safe, but very small base62 decoder:

function(a,b,c,d){for(b=c=0;d=a.charCodeAt(c++);b=b*62+d-[,48,29,87][d>>5]);return b}

@sebastien-p
Copy link
Author

@atk : thanks, the b=b*62+d-[,48,29,87][d>>5] part is awesome, exactly what I needed !

@atk
Copy link

atk commented Aug 26, 2011

You're welcome, @sebastien-p :-)

I would really like to see more comments in the annotated part. I have only just worked out what the first part of the for loop does (leading to the false-y charCodeAt(-1) in the second for-loop-part if a is not string or not base62).

@sebastien-p
Copy link
Author

@atk : is it better now ? :) Can you explain the line I kept from your code as I don't always understand well those bitwise tricks ? Thanks.

@atk
Copy link

atk commented Aug 30, 2011

Thanks, much better now. Of course I can explain this line (except of the b*62 part, which seems pretty self-explaining to me):

// We are expecting either numbers (ascii 48-58), uppercase letter (ascii 65-90) and lowercase letters (ascii 97-122)
// and want to map the numbers to 0-9, the uppercase letters to 36-61 and the lowercase letters to 10-35; therefore,
// we integer divide the character code by 32 using shift right 5, so numbers will yield 1, uppercase letters 2 and lowercase 3
// and let this result select the corresponding substractor from a sparse array (because the extra comma is smaller than -1):
[,48,29,87][d>>5]

@sebastien-p
Copy link
Author

@atk : thank you, I understand it a little more now :) but still don't manage to apply this kind of hack to the encoding function :(

@atk
Copy link

atk commented Aug 30, 2011

it does not apply there, because we'd need another formula than d>>5 to filter 0-9, 10-35 and 36-61 to 0, 1 and 2. If I find one, I'll tell you.

@sebastien-p
Copy link
Author

@atk : I would be very interested to know, thank you.

@atk
Copy link

atk commented Aug 30, 2011

no formula I could think of would be shorter than x>35?87:x>10?29:48.

@sebastien-p
Copy link
Author

@atk : ok, thanks. If you want to help, I released the new version of the encoding function, still 4 bytes to go :) https://gist.github.com/1168420

@sebastien-p
Copy link
Author

a === (/\W|_/.test(a += "") || a) could be great instead of a === (a += "") && /^[a-z\d]+$/i.test(a) but sadly doesn't prevent passing an empty string as argument.

@atk
Copy link

atk commented Sep 18, 2011

how about saving at least 1 byte with a===(/^[a-z\d]+$/i.exec(a)||0)[0] which should take care of empty strings? Or even shorter: a===(/\W|_|^$/.test(a)||a) in which we use the property of /^$/ to match empty strings?

@sebastien-p
Copy link
Author

@atk : thanks, base62 decode is now 4 bytes shorter :)

@atk
Copy link

atk commented Sep 20, 2011

@sebastien-p: test coerces its argument to string, so a+='' has no function there. You may want to use a===(/\W|_|^$/.test(a)||a+'')

@sebastien-p
Copy link
Author

@atk : yep, I know, but a needs to be a string for a.charCodeAt(c++) to work, so I force coercion here on purpose.

@atk
Copy link

atk commented Sep 20, 2011

For a not to be a string and to be coerced to a string that coerced into a valid base62 string, it would have to be an object with a toString method, so handling non-strings is rather pointless, isn't it?

@sebastien-p
Copy link
Author

@atk : you're right, input value validation is optional and the whole entry would be shorter without it. I added it because it fits and mostly because I needed the function to be designed this way.

@yckart
Copy link

yckart commented Jan 14, 2013

true // -1
false // -1

@Quacky2200
Copy link

I found this useful and converted it into C# if anyone ever needs it. Not intended to be 140 bytes small.

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