/    Sign up×
Community /Pin to ProfileBookmark

Mimic Javascript for the ‘The Nine Billion Names of God’

I did read the other day an amazing tale from Arthur C.Clarke, The Nine Billion Names of God about Tibetan monks looking to write down all the possible 9 letters combination of the Tibetan alphabet, so the real name of God is finally spelled, and the whole purpose of the human race is fulfilled.

For that purpose, and after centuries doing it manually, they finally rent a computer.

I liked the tale and wanted to mimic it using my own laptop. I already wrote a Basic program to swap nine ASCII characters. But my ultimate goal is to post a javascript in my blog so readers can see it working while they read along.

Dmboyd helped me to set this code ahead:

[CODE]var n = 41;
var letra = new Array();
for (var i = 0; i < n; ++i)
letra.push(String.fromCharCode(i + 0x0f40));
for (var p1 = 0; p1 < n; ++p1)
for (var p2 = 0; p2 < n; ++p2)
for (var p3 = 0; p3 < n; ++p3)
for (var p4 = 0; p4 < n; ++p4)
for (var p5 = 0; p5 < n; ++p5)
for (var p6 = 0; p6 < n; ++p6)
for (var p7 = 0; p7 < n; ++p7)
for (var p8 = 0; p8 < n; ++p8)
for (var p9 = 0; p9 < n; ++p9)
document.writeln(letra[p1]
+ letra[p2]
+ letra[p3]
+ letra[p4]
+ letra[p5]
+ letra[p6]
+ letra[p7]
+ letra[p8]
+ letra[p9]
+ “<br>”);
[/CODE]

Unfortunately, there still exist two small problems:

MISSING CODE POINT
Tibetan letters start at U+0F40 and end at U+0F6C, but the last 3 don’t show up in Arial, so I limited the alphabet to the first 41 letters. Besides, code point U+0F48 is missing (go figure why) so the alphabet feeding iteration should skip this number.

How could we do that?

MEMORY OVERRUN
The printout ends after 10256 lines due to memory shortage. The current

[CODE]document.writeln(letra[p1][/CODE]

must be replaced by some in-place or batch printing or cleaning the memory so no limits affect the iterations within the design boundaries.

Do you have any idea how to do that?

Many thanks for any hint!

to post a comment
JavaScript

15 Comments(s)

Copy linkTweet thisAlerts:
@MaydayApr 03.2009 — Stop now! Learn a lesson from the ill-fated protagonists of the story! If you succeed, the universe will cease to exist! Ahhhhh! :eek:

He he he ?
Copy linkTweet thisAlerts:
@mrhooApr 03.2009 — Despite the title, you are not testing 9 billion unique names, but 9^41,

or 1330279464729113300000000000000000000000.

(1.3302794647291133e+39).

unicode tibetan allocates 2 bytes per character, or 18 per name, plus 2 more for a comma and a space.

Multiply the names times 20 bytes.

How big is your hard drive?
Copy linkTweet thisAlerts:
@dmboydApr 06.2009 — Despite the title, you are not testing 9 billion unique names, but 9^41,

or 1330279464729113300000000000000000000000.

(1.3302794647291133e+39).

unicode tibetan allocates 2 bytes per character, or 18 per name, plus 2 more for a comma and a space.

Multiply the names times 20 bytes.

How big is your hard drive?[/quote]

That would result in
[list]
  • [*]24197642500969110366800103144 TiB of space used (according to the OS), or
  • [*]26605589294582266196894977837 TB of space used (according to hard drive manufacturers).
  • [/list]
    This means that you would need a very large hard drive!

    Disclaimer: The large numbers contained within this post were generated using the Python programming language, and in no way is the author of this post responsible for what may happen to your computer should you attempt to complete the task described by the OP. :p
    Copy linkTweet thisAlerts:
    @felgallApr 06.2009 — If you place an order for all the hard drives that can be built over the next few thousand years then at the end of that time you should have enough hard drive space to at least be able to add more drive space along the way before the script reaches the point of needing it.
    Copy linkTweet thisAlerts:
    @diegorodriguezauthorApr 07.2009 — Hehe...

    My 1st question was how to skip a single letter 0x0f48 in the feeding loop

    [CODE]var n = 41;
    var letra = new Array();
    for (var i = 0; i < n; ++i)
    letra.push(String.fromCharCode(i + 0x0f40));
    [/CODE]


    Any idea?

    The 2nd question was how to write all the results in a single line, nothing saved, nothing stored. Just the fun of seeing the swapping letters. So writeln is not the right one.

    [CODE]document.writeln(letra[p1][/CODE]

    wite command doesn't seem to make any difference, listing combinations in a single ever growing webpage.

    Any idea?
    Copy linkTweet thisAlerts:
    @dmboydApr 07.2009 — The answer to the first question is easy. Just use enclose the letra.push line inside an if block and modify the for loop to include n:
    for (var i = 0; i &lt;= n; ++i)
    if (i != 8)
    letra.push(String.fromCharCode(i + 0x0f40));


    The answer to the second question is a bit more difficult. The obvious solution is to use the DOM to replace the text of an HTML element with the necessary code. However, with the current code structure, I can't seem to figure out how to delay things to allow the browser to NOT freeze, much less display the results. There are a few improvements to JavaScript that Mozilla has done in version 1.7, but they only work in Firefox 2.x and beyond (not sure about Seamonkey, Camino, etc. versions). The generator-iterator combination would solve the problem easily. If you can live with that, then that's great. Otherwise, your code will need some re-factoring.

    Edit: Here is some code that uses the generator-iterator bits:
    [code=html]<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title>The Nine Billion Names of God</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    </head>
    <body onload="startNameChange()">
    <div id="PageContainer">
    <p id="CurrentName">
    Your browser doesn't support JavaScript. Please turn it on or
    try a different browser.
    </p>
    </div>
    <script type="application/javascript;version=1.7"
    src="names.js"></script>
    </body>
    </html>[/code]


    // names.js
    function startNameChange() {
    var textNode = document.getElementById('CurrentName').firstChild;
    var d = doNameChange();
    textNode.nodeValue = '';
    setInterval(function() { textNode.nodeValue = d.next(); }, 500);
    }

    function doNameChange() {
    var n = 41;
    var letra = new Array();
    for (var i = 0; i &lt;= n; ++i)
    if (i != 8)
    letra.push(String.fromCharCode(i + 0x0f40));
    for (var p1 = 0; p1 &lt; n; ++p1) {
    for (var p2 = 0; p2 &lt; n; ++p2) {
    for (var p3 = 0; p3 &lt; n; ++p3) {
    for (var p4 = 0; p4 &lt; n; ++p4) {
    for (var p5 = 0; p5 &lt; n; ++p5) {
    for (var p6 = 0; p6 &lt; n; ++p6) {
    for (var p7 = 0; p7 &lt; n; ++p7) {
    for (var p8 = 0; p8 &lt; n; ++p8) {
    for (var p9 = 0; p9 &lt; n; ++p9) {
    yield (letra[p1]
    + letra[p2]
    + letra[p3]
    + letra[p4]
    + letra[p5]
    + letra[p6]
    + letra[p7]
    + letra[p8]
    + letra[p9]);
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    Copy linkTweet thisAlerts:
    @haulinApr 10.2009 — i played a while with the function i posted here and i made this:
    [code=html]<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>limit chars</title>
    <script type="text/javascript">
    function nineBillionNamesOfGod()
    {
    if (num<variations && !paused)
    {
    for (var i=k; i>0; i-=1)
    {
    word=String.fromCharCode(Math.floor(num/Math.pow(n,k-i))&#37;n+0x41)+word;
    }

    target.innerHTML=word;
    word="";
    num+=1;
    timeout=setTimeout(function(){nineBillionNamesOfGod();}, 10);
    }
    }
    function init()
    {
    target=document.getElementById("target_div");
    document.getElementById("btn_start").onclick=function()
    {
    clearTimeout(timeout);
    document.getElementById("btn_pause").value="pause";
    num=0;
    paused=false;
    nineBillionNamesOfGod();
    }
    document.getElementById("btn_pause").onclick=function()
    {
    if (num!==0)
    {
    if (!paused)
    {
    clearTimeout(timeout);
    paused=true;
    this.value="continue";
    target.innerHTML+=" is the "+num+". name of God"
    } else
    {
    paused=false;
    this.value="pause";
    nineBillionNamesOfGod();
    }
    }
    }
    }
    var n=41, k=9, num=0, paused, target, timeout, variations=Math.pow(n,k), word="";
    window.onload=init;
    </script>
    </head>
    <body>
    <div id="target_div"></div>
    <p>
    <input id="btn_start" type="button" value="start">
    <input id="btn_pause" type="button" value="pause">
    </p>
    </body>
    </html>[/code]

    it calculates the word using its sequential number. however already Math.pow(10,9) gives me wrong value, so i can never get to Math.pow(41,9), which should be around 10^39. the Number.MAX_VALUE is approx. 10^308, so it should work. when i do:
    [CODE]variations=1000000000000000000000000000000000000000; //39 zeros
    alert(variations);[/CODE]

    it displays 1+e39, right as it should. does anyone know what's wrong with the Math.pow() function?

    also, how can i display the damn tibethian letters? if i do fromCharCode(0x0f40) or bigger, i only see empty squares.
    Copy linkTweet thisAlerts:
    @dmboydApr 10.2009 — Do you have a Unicode font installed? Is your browser's encoding set to UTF-8 when you view that page?
    Copy linkTweet thisAlerts:
    @haulinApr 10.2009 — haha. i'm stupid. default font was set to regular Arial, so it doesn't have these. when i added
    [CODE]
    <style type="text/css">
    body {font-family: Arial Unicode MS;}
    </style>
    [/CODE]

    suddenly the funny-looking characters appeared ? but any guesses about the large numbers?
    Copy linkTweet thisAlerts:
    @dmboydApr 10.2009 — 327381934393961 = Math.pow(41, 9)

    I don't know what's wrong with yours, but using Firefox 3.1b3 in Windows XP, it displays things perfectly fine.

    Edit: Windows XP's Calculator gives the same result.

    Edit 2: Math.pow(10, 14.515054710477619) is approximately equal to Math.pow(41,9):
    327381934393960.75 = Math.pow(10, 14.515054710477619)
    327381934393961.00 = Math.pow(41, 9)
    Copy linkTweet thisAlerts:
    @diegorodriguezauthorApr 12.2009 — I am pretty OK with splitting the code and host the js file separately. I already uploaded it to http://www.filefactory.com/file/aga7dab/n/names_js, indeed.

    Normaly, I don't like that because then I need to keep a separate control on both the main page and the js hosting, to prevent dead links. Anyway, I guess I could live with it.

    A problem I got, though, is that I am planning to host the main file in my blog at blogger, so I can't place the <body onload="startNameChange()"> part of your code for an individual post.

    I would rather place a form somewhere with a button inside to launch names.js instead. Any sample of such a form?

    Ah... On using a variations function instead of the nested loops, it's a nice and elegant option, but I sincerely think it will obscure what we are doing, and probably slow down the program.
    Copy linkTweet thisAlerts:
    @Declan1991Apr 12.2009 — Despite the title, you are not testing 9 billion unique names, but 9^41,

    or 1330279464729113300000000000000000000000.

    (1.3302794647291133e+39).[/QUOTE]

    You mixed up the order there, it's the amount of possible letters to the power of the length of the word.

    There are 1.27e14 nine letter words with each letter different, and 3.27e14 if the same letter is allowed more than once.
    Copy linkTweet thisAlerts:
    @haulinApr 15.2009 — I don't know what's wrong with yours, but using Firefox 3.1b3 in Windows XP, it displays things perfectly fine.[/QUOTE]
    my bad again. there is nothing wrong with the code. i just used win calc to compare the results and of course i calculated 9^41 instead of 41^9...:rolleyes:
    I can't place the <body onload="startNameChange()"> part of your code for an individual post. I would rather place a form somewhere with a button inside to launch names.js instead.[/QUOTE]
    you can do what i did in my version. simply at the end of the names.js file assign the startNameChange as a callback function for window.onload:
    [CODE]
    window.onload=startNameChange; //no parentheses
    [/CODE]

    shame that clarke didn't describe all the criteria for the god names in his story. we will never know how did he come up with the number 9 billion. according to this page (search for "billion"), tibetan alphabet has 56 different characters, that would make 5.4e+15 different words. so either the rules were much more strict than we think (the only one mentioned in the story is that there can't be more than 3 same consecutive characters) or they didn't use all the letters... ?
    Copy linkTweet thisAlerts:
    @diegorodriguezauthorApr 16.2009 — Sorry, I don't undetstand the mechanics of it. First, I add [CODE]window.onload=startNameChange; //no parentheses[/CODE]
    at the end of the js file, and then I place a button inside a form to launch the js file, right?

    Any simple sample on a form with a button inside to launch the js?

    Thanks!
    Copy linkTweet thisAlerts:
    @haulinApr 16.2009 — no, sorry i forgot to mention that you don't need any form to do it, unless you really want to. that line in just another (unobtrusive) way how to do
    [CODE]<body onload="startNameChange()">[/CODE], so you can keep all your javascript instructions inside the names.js file. it does exactly the same, that is launches the function after the page is loaded. if you insist on starting it with a button, just do it on its click event (instead of load as in the body element):
    [code=html]
    <p>
    <input type="button" value="start" onclick="startNameChange()">
    </p>
    [/code]

    or you can use the unobtrusive way here again. i did it in my version, so have a look at that.
    ×

    Success!

    Help @diegorodriguez spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 BETA 5.7,
    whats_new: community page,
    up_next: more Davinci•003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinci•003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @AriseFacilitySolutions09,
    tipped: article
    amount: 1000 SATS,

    tipper: @Yussuf4331,
    tipped: article
    amount: 1000 SATS,

    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,
    )...