HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Iterate from "0" to "ZZZZZ"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
iteratefromzzzzz

Problem

I was given an assignment, it was as follows:

Give a JS code snippet which writes to the console from:
"0" to "ZZZZZ" all the combination of the characters of a-z, 0-9 and A-Z.

Is my solution correct?
I am sure there are better ways to achieve the same, can anybody show some?
My code is:

function createCharSet(){
    var charset = "", c;

    for(c=48;c-1;i--){
        c = charSet.indexOf(arr[i])+1;

        if(c==radix){
            arr[i]=charSet[0];
            if(i==0)
                return;
        }else{
            arr[i]=charSet[c];
            break;
        }
    }

    return arr.join("");
}

function iterate() {
    var 
        charSet = createCharSet(),
        maxLen = 4,
        len,
        i,
        arr,
        curr;

    for(len = 1;len<maxLen+1;len++){
        arr = [];
        for(i=0;i<len;i++){
            arr.push(charSet[0]);
        }

        curr = arr.join("");
        while(curr) {
            console.log(curr);
            curr = getNext(curr, charSet);
        };
    }

}

iterate();

Solution

Minor observations:

-
I'd just hardcode the charset in this case. Doing so is faster to write (and a lot more explicit) than building it with a bunch of loops.

-
The modulo operator % is a good friend to have for this, as it'll let you "wrap around" array indices.

Overall, there's too much code here, I think. This is just counting in base 62.

It'd be awesome if Number.prototype.toString() accepted 62 as an argument, but, unfortunately, it only seems to accept bases 2-36. Similarly, it'd be great if we could somehow use the built-in base64 encoding function (btoa), but it's, well, base 64 (and it's got other issues). So we do have to roll our own.

Now, if this was base 10, we could obviously just do

var limit = Math.pow(10, 5); // i.e. 100000

for(var i = 0 ; i < limit ; i++) {
  console.log(i);
}


which will print 0-99999.

Using this same basic setup, we can print our base62 values. Our limit will be \$base^{numberOfDigits}\$ just like \$10^5\$ will end up printing five 9s. So for 0-ZZZZZ we'll need to loop from zero to Math.pow(62, 5).

And of course, we'll have to do the actual base62 conversion. The basic algorithm is:

  • Get the char corresponding to \$value\bmod base\$ (e.g. charset[538 % 62] => charset[42]) and add it to the output string.



  • Set \$value\$ to the quotient of \$\frac{value}{base}\$ (e.g. Math.floor(538 / 62) => 8).



  • If value is bigger than zero, go to step 1. Otherwise, return the output.



In code:

var output = "";
do {
  output = charset[value % base] + output;
  value = (value / base) | 0; // bitwise floor trick
} while(value > 0);
return output;


Putting it all together, I get this:

// define our base62 function (using an IIFE)
var toBase62 = (function () {
  var charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
      base = charset.length; // 62, natch

  return function (value) {
    // TODO: It'd be nice to guard against negative values here (see comments)
    var string = "";
    do {
      string = charset[value % base] + string;
      value = (value / base) | 0;
    } while(value > 0);
    return string;
  }
}());

// loop for a long, long time
for(var i = 0, l = Math.pow(62, 5) ; i < l ; i++) {
  console.log( toBase62(i) );
}


Note that it takes forever to print all the 916,132,832 values from 0 up to \$62^5\$. JS ain't that fast. I haven't explored optimization, so for testing, I'd advice using (much) fewer iterations.

Code Snippets

var limit = Math.pow(10, 5); // i.e. 100000

for(var i = 0 ; i < limit ; i++) {
  console.log(i);
}
var output = "";
do {
  output = charset[value % base] + output;
  value = (value / base) | 0; // bitwise floor trick
} while(value > 0);
return output;
// define our base62 function (using an IIFE)
var toBase62 = (function () {
  var charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
      base = charset.length; // 62, natch

  return function (value) {
    // TODO: It'd be nice to guard against negative values here (see comments)
    var string = "";
    do {
      string = charset[value % base] + string;
      value = (value / base) | 0;
    } while(value > 0);
    return string;
  }
}());

// loop for a long, long time
for(var i = 0, l = Math.pow(62, 5) ; i < l ; i++) {
  console.log( toBase62(i) );
}

Context

StackExchange Code Review Q#51652, answer score: 6

Revisions (0)

No revisions yet.