1

I am trying to create unique identifiers with a script I am writing in JavaScript. The constraints I am applying to these identifiers are the following:

  1. The first nine characters of the identifier must be a random sequence of digits. I am defining 'digits' as the set over {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.
  2. The last character of each identifier must be a random, single English uppercase letter. I am defining this set over {A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z}.

I understand that true randomness isn't represented by any programming language. Some programming languages simply have a library function that simulates "randomness", but I don't think any language actually implements the idea of true randomness. Nevertheless, let's pretend that the JavaScript Math.random() function is the best implementation of randomness.

Here is the JavaScript code that I have so far:

// the numbers in this array represent the utf-8 codes for the uppercase letters A-Z
var uppercaseLetters = new Array(65,66,67,68,69,70,71,72,73,74,75,76,77,78,
    79,80,81,82,83,84,85,86,87,88,89,90);

// http://stackoverflow.com/questions/16753876/javascript-button-to-pick-random-item-from-array
var randomElement = uppercaseLetters[Math.floor(Math.random() * 
    uppercaseLetters.length)];

document.write(String.fromCharCode(randomElement));

convertedElement = String.fromCharCode(randomElement);

// document.write("<br /> <br />");

// borrowed String.fromCharCode from some part of the Mozilla developer website
// you can also see the utf-8 character set on wikipedia:
// http://en.wikipedia.org/wiki/UTF-8
/* for(var index = 0; index < 26; index++) {
        document.write(String.fromCharCode(uppercaseLetters[index]));
} */

document.write("<br /> <br />");

var result;    

for(var count = 0; count < 9; count++) {
    var randomNumber = Math.ceil((Math.random() * 10) - 1);
    // var randomNumber = Math.ceil((Math.random() * 9)); may also work
    document.write(randomNumber);
} 

result += convertedElement;
document.write(result);

// http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem
/* function createDigitString() {
for(var count = 0; count < 9; count++) {
        var randomNumber = Math.ceil((Math.random() * 10) - 1);
        // var randomNumber = Math.ceil((Math.random() * 9)); may also work
        document.write(randomNumber);
    } 
} */

And here is the HTML to display it:

<!DOCTYPE html>
<html>
<head>
    <base href="file:///C:/Users/sillyname/" /> 
    <script src="random-sequence.js"></script>
</head>

<body>
</body>
</html>

The two files are obviously stored in the same directory. So, this code should display a "random" 9-digit sequence, skip a few lines, and then display a "random" uppercase letter. Now, I want to combine the two by appending the letter to the number sequence. What is the best (or simplest) way to achieve this?

EDIT: I should also clarify that I want to maintain the two pieces of "random-simulating" code separately. In other words, I would like to store the final sequence in a variable while maintaining separability:

var finalSequence = nineRandomDigits + randomUppercaseLetter

EDIT: Alright, I think I have what I want thank everyone that contributed. Here is the final solution.

function randomUppercaseLetter() {
    var letter = String.fromCharCode(64 + Math.ceil(Math.random() * 26));
    return letter;
}

function randomNumber(len) {
    var randomNumber;
    var n = '';

    for(var count = 0; count < len; count++) {
        randomNumber = Math.ceil((Math.random() * 10) - 1);
        n += randomNumber.toString();
    }
    return n;
}

// Usage:
var finalSequence = randomNumber(9) + randomUppercaseLetter();

document.write(finalSequence);
brthomps
  • 43
  • 6
  • 1
    Remove the brs? Is it really that simple? – epascarello Nov 26 '13 at 18:39
  • The
    are simply there for readability.
    – brthomps Nov 26 '13 at 18:43
  • The problem with randomness is not that "most languages don't implement it", it's that computers are inherently *not random*. You need a special hardware device in order to produce actual, true randomness. Apparently you have not seen or understood the Matrix movies. ;-) – deceze Nov 26 '13 at 19:21
  • Thank you for that piece of knowledge. I've seen the Matrix, but that was over a decade ago. Now I am 23 years old. It's amazing how little we really know as a species. If we were living 20 years ago, you wouldn't have the capability to communicate that piece of information to me this easily, nor would I have the means to receive it. The Internet, computers, and technology in general is still revolutionizing everything we know... or everything we think that we know. :) – brthomps Nov 26 '13 at 19:32
  • Watch them again with that in mind. Spoiler: Zion is a RNG. ;-) – deceze Nov 26 '13 at 19:37

3 Answers3

6

This single expression will produce the required ID:

var id = Array.apply(0, Array(9)).map(function() {
    return String.fromCharCode(48 + Math.floor(10 * Math.random()));
}).join('') + String.fromCharCode(65 + Math.floor(26 * Math.random()));

The Array.apply(0, Array(9)).map() is a trick (see here, and here) used to avoid an explicit for loop to produce the first 9 numbers.

To deobfuscate slightly, use a helper function:

function randChar(start, count) {
    return String.fromCharCode(start + Math.floor(count * Math.random()));
}

function generateId() {
    return Array.apply(0, Array(9)).map(function() {
        return randChar(48, 10);
    }).join('') + randChar(65, 26);
}
Community
  • 1
  • 1
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Wow, JavaScript is even more amazing than I thought. At first, I thought to myself, "It's cool that you got my code shrunk down to three lines, but it's not very readable." Then, I read the rest of your answer and followed the links, which immensely helped clarify what I didn't understand. Will you be my JS Sensai? :P – brthomps Nov 27 '13 at 06:33
  • 1
    If you know a better way, it's worth sharing it as an answer rather than as comments like "you're wrong" or "you're naive". Anyway, thanks for having pointed out this "almost never zero" problem Dinosaur ;) –  Nov 27 '13 at 08:00
  • @wared I gave the solution in comment #3 to your question - you needed to multiply by 26 instead of 25. – Alnitak Nov 27 '13 at 09:22
  • Well, I guess I'm also a bit susceptible today ^^' –  Nov 27 '13 at 10:27
1

Here is the final JavaScript solution I came up with, and the one that I chose to stick with. Alnitak provides an amazing JS answer, which also carries out the same job, but in a more elegant and "magical" way. I suggest looking at his answer in detail if you are really interested in mastering JavaScript.

function randomUppercaseLetter() {
    var letter = String.fromCharCode(64 + Math.ceil(Math.random() * 26));
    return letter;
}

function randomNumber(len) {
    var randomNumber;
    var n = '';

    for(var count = 0; count < len; count++) {
        randomNumber = Math.floor(Math.random() * 10);
        n += randomNumber.toString();
    }
    return n;
}

// Usage:
var finalSequence = randomNumber(9) + randomUppercaseLetter();

document.write(finalSequence);

Just for ease of testing and clarification, use this HTML to show the results:

<!DOCTYPE html>
<html>
<head>
    <base href="file:///C:/Users/aUser/" /> 
    <script src="random-sequence.js"></script>
</head>

<body>
</body>
</html>

I named the HTML file random-sequence.html. Both the HTML and JS files are stored in the same directory.

brthomps
  • 43
  • 6
  • instead of using `Math.ceil() - 1`, use `Math.floor()`. As written your code would produce `-1` for a digit if `Math.random()` returns 0.0 exactly. – Alnitak Nov 27 '13 at 11:45
  • So 'Math.ceil((Math.random() * 10) - 1)' would be translated into 'Math.floor(Math.random() * 10)'? – brthomps Nov 28 '13 at 00:28
0

You can create a var before your for and add the letter at the end like this:

var result = "";

for(var count = 0; count < 9; count++) {
    var randomNumber = Math.ceil((Math.random() * 10) - 1);
    result+= randomNumber;
} 

result+= randomElement;
document.write(result);

Edit: working jsfiddle

Shryme
  • 1,572
  • 1
  • 14
  • 22