Language detail: JavaScript

Coverage: 76.92%
number of '+' ratings
contribution for coverage

Unsolved challenges

codes

Feed

Used modules

next >>

環境変数の取得 (Nested Flatten)
WSHのJScriptです。WSHでは、WScript.Shellオブジェクトから取得可能です。
1
2
3
4
5
6
7
sh = new ActiveXObject('WScript.Shell');
env = sh.Environment;
stdIn = WScript.StdIn;
stdOut = WScript.StdOut;
stdOut.WriteLine('キー名を指定してください');
key = stdIn.ReadLine();
stdOut.WriteLine('%' + key + '% == ' + env(key));
LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する (Nested Flatten)
参考までに、同じものをJavaScriptで投稿しておきます。WSHで実行するように作っているので、これを試すには拡張子jsを付けて保存したファイルを直接実行してください。Windowsでない方にはごめんなさい。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function GetTinyUrlString(url)
{
    var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    xmlhttp.open("GET", "http://tinyurl.com/api-create.php?url=" + url);
    xmlhttp.send();
    var result = xmlhttp.responseText;
    if (result.toLowerCase() == "error")
    {
        throw "Tinyurl returns error";
    }
    return result;
}

WScript.Echo(GetTinyUrlString("http://ll.jus.or.jp/2008/info/xgihyo"))
IPv4アドレスのマスクの変換 (Nested Flatten)

「ipaddr2mask」でアドレス→数値変換。 「mask2ipaddr」で数値→アドレス変換。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function format(num, dec1, dec2, minlen){
    var num1 = new Number(parseInt(num, dec1)).toString(dec2);;
    while(num1.length < minlen) num1 = "0" + num1;
    return num1;
}

function ipaddr2mask(ipaddr){
    var ad = ipaddr.split(".");
    var str = "";
    for(var i = 0; i < ad.length; i++){
        str += format(ad[i],10,2,8);
    }
    for(var i = str.length-1; i > 0 ; i--){
        if(str.charAt(i)!=0){return i+1;}
    }
    return 0;
}

function mask2ipaddr(mask){
    var m1 = format(mask,10,10,1);
    var str = "";
    while(str.length < 32){ str+= (str.length < m1) ? "1" : "0"; }
    var ipaddr = "";
    for(var i = 0; i < 4; i++){
        if(i > 0){ ipaddr+="."; }
        ipaddr+=format(str.substr(i*8, 8),2,10,1);
    }
    return ipaddr;
}
ストレンジアトラクタの描画 (Nested Flatten)
JavaScriptで Clifford Attractorsを描画してみました。パラメーターを変更することで、
いろいろな形を描画することができます。 Firefox 2.0.0.6, Google Chrome 1.0.154.48, 
Opera 9.23で動作を確認しました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<html>
<head>
    <script type="text/javascript">
        var $ = function (i) { return document.getElementById(i); };

        Function.prototype.repeat = 
        function (t, o) {
            var _ = this;
            return setInterval(function () { _.apply(o); }, t);
        };

        // アトラクター
        var Attractor = 
        function (a, b, c, d) {
            var _ = $('canvas');

            this.a = a;           // パラメーター
            this.b = b;
            this.c = c;
            this.d = d;

            this.h = 300;         // 高さ
            this.w = 300;         // 横幅
            this.ox = this.w / 2; // 原点
            this.oy = this.h / 2;
            this.s = (this.w > this.h) ? this.h / 4 : this.w / 4;
            this.x = 0;           //  X座標
            this.y = 0;           //  Y座標

            _.setAttribute('height', this.h); _.setAttribute('width', this.w);

            this.C = _.getContext('2d'); // 描画コンテキスト
        }

        Attractor.prototype.draw = 
        function () {
            var x = Math.sin(this.a * this.y) + this.c * Math.cos(this.a * this.x);
            var y = Math.sin(this.b * this.x) + this.d * Math.cos(this.b * this.y);

            this.C.fillRect(this.ox + x * this.s, this.oy - y * this.s, 1, 1);

            this.x = x; this.y = y;
        }

        window.onload = 
        function () {
            var A = new Attractor(-1.4, 1.6, 1.0, 0.7);
            A.draw.repeat(1, A);
        };
    </script>
</head>
<body>
    <canvas id="canvas"></canvas>
</body>
</html>
16進数から10進数の変換 (Nested Flatten)
初投稿です。 数値文字列として変換してみました。 変換後の最大値はおそらくNumber.MAX_VALUEになるかと。 # とりあえず4-500桁ぐらいまでは動作検証しました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* --------------------------------------------------------------------------- */
String.prototype.toCharArray=function(){
  var arr = new Array(this.length);
  for(var i = 0; i < this.length; i++){ arr[i] = this.charAt(i); };
  return arr;
};
/* --------------------------------------------------------------------------- */
function add(strnum1, strnum2){
  var arr1 = strnum1.toCharArray().reverse();
  var arr2 = strnum2.toCharArray().reverse();
  var max = (arr1.length > arr2.length ? arr1.length : arr2.length) - 1;
  var strsum = "";
  for(var i = 0, up = 0; i <= max; i++){
    var c1 = i < arr1.length ? parseInt(arr1[i],10) : 0;
    var c2 = i < arr2.length ? parseInt(arr2[i],10) : 0;
    c1 += up;
    c1 += c2;
    up = Math.floor(c1/10);
    c1 %= 10;
    strsum = c1 + strsum;
    if(i == max) strsum = up+strsum;
  }
  return strsum;
};
/* --------------------------------------------------------------------------- */
function sum(arr){
  var strsum = "";
  for(var i = 0; i < arr.length; i++){
    strsum = add(strsum, arr[i]);
  }
  return strsum.replace(/^0*/,"");
};
/* --------------------------------------------------------------------------- */
function multiple(a, b){
  var arr_a = a.toCharArray().reverse();
  var arr_b = b.toCharArray().reverse();
  var arr_c = new Array(arr_b.length);
  var max = arr_a.length-1;
  for(var i = 0, zeropad=""; i < arr_b.length; i++,zeropad+="0"){
    var str_c = "";
    for(var j = 0, up=0; j<arr_a.length; j++){
      var c = (parseInt(arr_a[j], 10) * parseInt(arr_b[i],10));
      c+=up;
      up = Math.floor(c/10);
      c %= 10;
      str_c = c+str_c;
      if(j==max && up>0) str_c=up+str_c;
    }
    str_c+=zeropad;
    arr_c[i] = str_c;
  }
  return sum(arr_c);
};
/* --------------------------------------------------------------------------- */
function hex2decimal(hexstr){
  var template = "0123456789ABCDEF";
  var arr = hexstr.toUpperCase().substring(2).toCharArray().reverse();
  for(var i = 0, hex="1"; i < arr.length; i++, hex=multiple(hex,"16")){
    var numc = "" + template.indexOf(arr[i]);
    var mult = multiple(numc, hex);
    arr[i] = mult;
  }
  var decstr=sum(arr);
  if(decstr.length==0) desctr="0";
  return decstr;
};
複素数 (Nested Flatten)
使うときに楽だろうと思い、引数の型に幅を持たせてみました。

例)
var c0 = new Complex(0, 1);
var c1 = new Complex([1, 1]);
var c2 = new Complex({r:3, i:-4});
var c3 = new Complex("5-8i");

alert((new Complex("3+2i")).mul("5-i").mul("-6+2i").div("5-i").div("-6+2i"));
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 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
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
var Complex = function (arg0, arg1){
    arg0 = arg0 || 0;
    arg1 = arg1 || 0;
    if (typeof arg0 == "number" && typeof arg1 == "number"){
        this.r = arg0;
        this.i = arg1;
    } else {
        var tmp = Complex.conv(arg0)
        this.r = tmp.r;
        this.i = tmp.i;
    }
};

// 加減乗除メソッドは破壊的
Complex.prototype = {
    toString: function(){return Complex.toString(this);},
    valueOf:  function(){return Complex.toString(this);},
    abs: function(){return Complex.abs(this);},
    add: function(cn){
        var tmp = Complex.add(this, cn);
        this.r = tmp.r;
        this.i = tmp.i;
        return this;
    },
    sub: function(cn){
        var tmp = Complex.sub(this, cn);
        this.r = tmp.r;
        this.i = tmp.i;
        return this;
    },
    mul: function(cn){
        var tmp = Complex.mul(this, cn);
        this.r = tmp.r;
        this.i = tmp.i;
        return this;
    },
    div: function(cn){
        var tmp = Complex.div(this, cn);
        this.r = tmp.r;
        this.i = tmp.i;
        return this;
    }
};

// 以下はインスタンスのメソッドではない
// 引数をインスタンスもどき(メソッドなしでプロパティr, iのみのオブジェクト)に変換する関数
Complex.conv = function(arg){
    if (typeof arg == "object") {
        return {r: Number(arg.r || arg[0] || 0), i: Number(arg.i || arg[1] || 0)};
    } else if (typeof arg == "string") {
        var srcNum = "([+\\-]?(?:[0-9]+\\.?[0-9]*|0?\\.[0-9]+)(?:e[+\\-]?[0-9]+)?)";
        var reCNum = new RegExp("^(?:" + srcNum + "(?!i))?(?:" + srcNum + "i)?$", "i");
        reCNum.exec(arg.replace(/\s/g, "").replace(/(^|\+|-)i/i, "$11i"));
        return {r: Number(RegExp.$1), i: Number(RegExp.$2)};
    }
    return {r: Number(arg), i: 0};
};

// インスタンス相当を引数に取る関数
Complex.toString = function(cn){
    cn = Complex.conv(cn);
    return cn.r.toString() + (cn.i >= 0 ? "+" : "") + cn.i.toString() + "i";
};
Complex.abs = function(cn){
    cn = Complex.conv(cn);
    return Math.sqrt(cn.r * cn.r + cn.i * cn.i);
};
// 加減乗除関数は新しいインスタンスを返す
Complex.add = function(cn0, cn1){
    cn0 = Complex.conv(cn0);
    cn1 = Complex.conv(cn1);
    return new Complex(cn0.r + cn1.r, cn0.i + cn1.i);
};
Complex.sub = function(cn0, cn1){
    cn0 = Complex.conv(cn0);
    cn1 = Complex.conv(cn1);
    return new Complex(cn0.r - cn1.r, cn0.i - cn1.i);
};
Complex.mul = function(cn0, cn1){
    cn0 = Complex.conv(cn0);
    cn1 = Complex.conv(cn1);
    return new Complex(cn0.r * cn1.r - cn0.i * cn1.i,
                       cn0.i * cn1.r + cn0.r * cn1.i);
};
Complex.div = function(cn0, cn1){
    cn0 = Complex.conv(cn0);
    cn1 = Complex.conv(cn1);
    var absSq = cn1.r * cn1.r + cn1.i * cn1.i;
    return new Complex((cn0.r * cn1.r + cn0.i * cn1.i) / absSq,
                       (cn0.i * cn1.r - cn0.r * cn1.i) / absSq);
};
// 定義部はここまで

/* お題の計算。結果は以下
7+0i
3-15i
1+55i
1.1333333333333333-0.4i
3.605551275463989
*/
alert(
             Complex.add(new Complex(3, 1),  new Complex(4, -1))
    + "\n" + Complex.sub(new Complex(5, -9), new Complex(2, 6))
    + "\n" + Complex.mul(new Complex(5, 3),  new Complex(5, 8))
    + "\n" + Complex.div(new Complex(9, -7), new Complex(9, -3))
    + "\n" + Complex.abs(new Complex(2, 3))
);

// インスタンスを作る。引数は数値2つ、
// もしくは数値要素を2つ持つ(連想)配列か、複素数と解釈できる文字列
var c0 = new Complex(0, 1);
var c1 = new Complex([1, 1]);
var c2 = new Complex({r:3, i:-4});
var c3 = new Complex("5-8i");

// 絶対値を出してみる。上3行と下3行の結果は同じ。
alert(
             "|" + c0 + "| = " + Complex.abs(c0)
    + "\n" + "|" + c1 + "| = " + Complex.abs(c1)
    + "\n" + "|" + c2 + "| = " + Complex.abs(c2)
    + "\n" + "|" + c0 + "| = " + c0.abs()
    + "\n" + "|" + c1 + "| = " + c1.abs()
    + "\n" + "|" + c2 + "| = " + c2.abs()
);

// 計算1。引数なら文字列のままでも可。
// 下3行の計算は破壊的(c0の値が計算結果に変わる)
alert(
        "(" + c0 + ") + (" + c1   + ") = " + Complex.add(c0, c1)
    + "\n(" + c0 + ") - (" + c2   + ") = " + Complex.sub(c0, c2)
    + "\n(" + c0 + ") / (" + "-i" + ") = " + Complex.div(c0, "-i")
    + "\n(" + c0 + ") + (" + c1   + ") = " + c0.add(c1)
    + "\n(" + c0 + ") - (" + c2   + ") = " + c0.sub(c2)
    + "\n(" + c0 + ") / (" + "-i" + ") = " + c0.div("-i")
);

// 計算2。iの2乗。加減乗除の組み合わせ2つ。複素数を0で割ると0/0
alert(
      "i * i = " + Complex.mul("i", "i")

    + "\n(3+2i) * (5-i) * (-6+2i) / (5-i) / (-6+2i) = "
    + (new Complex("3+2i")).mul("5-i").mul("-6+2i").div("5-i").div("-6+2i")

    + "\n( (3+2i) + (4-i) ) * 2i * -.5i - (4-i) = "
    + Complex.add("3+2i", "4-i").mul("2i").mul("-.5i").sub("4-i")

    + "\n(1+2i) / 0 = " + Complex.div("1+2i", "0")
);

// 引数いろいろ。falsyな値や空配列は0+0iに
var testcases = [
    "-3-8i", "5", [0, 4], [2, -8],
    "-2+i", "-2-i", {r:-2.5, i:3e-2}, "-2E8 + I",
    "0", "i", Infinity, NaN, "", {}, null, undefined
];
for (var i = 0, rslt = ""; i < testcases.length; i++){
    rslt += (typeof testcases[i]) + ": " + testcases[i]
        + "\n\t\t" + (new Complex(testcases[i])) + "\n";
}
alert(rslt);
急勾配の判定 (Nested Flatten)
リストを前から見ていくこともできます。
後ろから見るほうがシンプルだけど、リストの長さが未確定の場合はこちらが有利。
ちなみに [1,0].isHeavySlope() は true になりますが何か?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Array.prototype.isHeavySlope = function() {
    if (this.length == 0) return true;
    var pre, sub;
    for each (var n in this) {
        if (pre == undefined) {
            sub = pre = n;
        } else {
            sub -= n;
            if (pre <= n || sub <= 0) return false;
            pre = n;
        }
    }
    return true;
}
効率は悪くないと思うけど、工夫はしてません。

仕様面ではっきりしないのは、
1.空リストは急勾配? not 急勾配?
2.問題文の「空列の和は0とします」をどう読むか。
  [0] は 0 + 空列  なので、not 急勾配になる?
  (sum の初期値を 0 とするか -∞ にするかというだけの話だけど)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Array.prototype.isHeavySlope = function() {
  var sum = 0;
  for (var i = this.length-1; i >= 0; i--) {
    if (this[i] <= sum) return false;
    sum += this[i];
  }
  return true;
}

>>> [].isHeavySlope()
true
>>> [0].isHeavySlope()
false
>>> [1,0].isHeavySlope()
false
>>> [0,1].isHeavySlope()
false
>>> [4,2,1].isHeavySlope()
true
>>> [3,2,1].isHeavySlope()
false
割り算の筆算 (Nested Flatten)

JavaScriptで。手抜きHTMLに入れてありますが、このままでも大抵のブラウザで動くと思います。

どうせすっきり書けないだろうしというわけで、整数範囲で割れるだけ割るのに加えて、商の各桁について「0」以外が得られてからf桁に達したら筆算を止める(f桁に達しないうちは小数点以下になっても続ける)、というのも入れてみました。で、予想以上にごちゃごちゃ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
<body>
<script>
function divOnPaper(n, m, maxFigs) {
    n = Math.floor(Number(n)); n = (isNaN(n)||n < 1) ? 1 : n;
    m = Math.floor(Number(m)); m = (isNaN(m)||m < 1) ? 1 : m;
    maxFigs = Math.floor(Number(maxFigs)); maxFigs = (isNaN(maxFigs)||maxFigs < 0) ? 0 : maxFigs;

    var q = [0], strQ = "", strN = n.toString(), qm, r = 0, exp = strN.length - 1;
    var limitToInt = !maxFigs, firstFig = false;
    var note = maxFigs ? "(up to " + maxFigs + " figures)" : "(within integer)",
        rowQ, rowMN = insSP(m) + " ) " + insSP(n), rowsQMR = "", rowR0, rowR1;

    while ((r || strN) && (limitToInt ? exp >= 0 : maxFigs)) {
        r *= 10;
        if (strN) {
            r += Number(strN.substring(0, 1));
            strN = strN.substring(1);
        }

        if (r >= m) {
            rowR1 =       repeatStr(" ", (rowMN.length - 2 * exp - insSP(r ).length)) + insSP(r );
            if (firstFig) {rowsQMR += rowR1.substring(rowR0.length) + "\n";} 

            qm = r - r % m;
            q[exp] = qm / m;
            r = r % m;

            rowsQMR += repeatStr(" ", (rowMN.length - 2 * exp - insSP(qm).length)) + insSP(qm) + "\n";
            rowsQMR += repeatStr(" ", (rowMN.length - 2 * exp - insSP(qm).length) - 1);
            rowsQMR += repeatStr("-", (insSP(qm).length) + 2) + "\n";
            rowR0 =       repeatStr(" ", (rowMN.length - 2 * exp - insSP(r ).length)) + insSP(r );
            rowsQMR += rowR0;

            firstFig = true;
        } else {
            if (firstFig || exp < 0) q[exp] = 0;
        }

        exp--; 
        if (firstFig) maxFigs--;
    }

    var i = exp; while (i > 0) q[i--] = 0;

    i = q.length - 1; while (i >= 0) strQ += q[i--].toString();
    if (typeof q[i] == 'number') strQ += ".";
    while (typeof q[i] == 'number') strQ += q[i--].toString();

    var summary = "n = m * q + r " + note + "\n" +
        "n: " + n + "\n" +
        "m: " + m + "\n" +
        "q: " + strQ + "\n" +
        "r: " + Number(r + "." + strN + "e" + (exp + 1));
    rowQ = repeatStr(" ", (rowMN.length - insSP(strQ).match(/(?:\d| )+/)[0].length)) + insSP(strQ);
    rowQ += "\n" + repeatStr(" ", insSP(m).length + 1) + repeatStr("-", (rowQ.length - insSP(m).length));

    return summary + "\n\n" +rowQ + "\n" + rowMN + "\n" + rowsQMR + "\n\n\n";

    function insSP(str) {
        return str.toString().replace(/(\d)(?=\d)/g, "$1 ");
    }
    function repeatStr(str, num) {
        return (new Array(num+1)).join(str);
    }
}
</script>

<form>
n: <input id="n" type="text">&nbsp;&nbsp;&nbsp;&nbsp;
m: <input id="m" type="text">&nbsp;&nbsp;&nbsp;&nbsp;
f: <input id="f" type="text">&nbsp;&nbsp;&nbsp;&nbsp;
<input id="calc" type="button" value="calc"><br>
<textarea id="rslt" style="font-size: 0.8em; line-height: 0.9em; width: 100%; height: 30em;"></textarea>
</form>

<script>
function calc(){
    n = document.getElementById("n").value;
    m = document.getElementById("m").value;
    f = document.getElementById("f").value;
    document.getElementById("rslt").value = divOnPaper(n, m, f);
}
document.getElementById("calc").onclick = calc;
document.write("<h4>examples:</h4><pre style=\"font-size: 0.8em; line-height: 0.9em;\">" +
    divOnPaper(1000, 71) + "\n" +
    divOnPaper(1000, 71, 4) + "\n" +
    divOnPaper(123456789, 57, 0) + "\n" +
    divOnPaper(123456789, 57, 2) + "\n" +
    divOnPaper(1000, 7, 0) + "\n" +
    divOnPaper(1000, 7, 2) + "\n" +
    divOnPaper(1000, 7, 3) + "\n" +
    divOnPaper(1000, 7, 4) + "\n" +
    "</pre>");
</script>
</body>
外部の実行ファイルを呼び出し (Nested Flatten)
折角なので、JScript版も。そういえば、VBScript版で、WScript.CreateObjectはCreateObjectで十分なのでした、あの場合。
1
2
3
4
5
var sh = new ActiveXObject("WScript.Shell")
WScript.Echo("メモ帳を起動(待たない)")
sh.Run("notepad.exe", 1, false)
WScript.Echo("メモ帳を起動(待つ)")
sh.Run("notepad.exe", 1, true)
ファイルサイズの取得 (Nested Flatten)
JScript で。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function fileSize(filepath){
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var file;
    if (fso.FileExists(filepath)){
        file=fso.GetFile(filepath);
        return file.Size;
    } else {
        return "ファイル「" + filepath + "」が存在しません。"
    }
}

var filepath = "./ファイルサイズ.js";
WScript.Echo(fileSize(filepath));
文字列を指定されたバイト数で分割 (Nested Flatten)

JavaScriptでやることもないと思うけども、JavaScriptで。Pen4 2.5GHz + Firefox 3で香川県をやると、Shift_JISで110ms、UTF-8で150ms前後でした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function splitBytes(src, len, encode){
    var re = {
        "Shift_JIS": [/[\u0000-\u007F\uFF61-\uFF9F]/g, /[\u0080-\uFF60\uFFA0-\uFFFF]/g],
        "UTF-8":     [/[\u0000-\u007F]/g, /[\u0080-\u07FF]/g, /[\u0800-\uFFFF]/g]
    }[encode];
    if (!(typeof src == "string") || !(typeof len == "number" && len > 0) || !re) return false;

    var enc = src;
    for (var i = 0; i < re.length; i++){
        enc = enc.replace(re[i], Math.pow(10, i));
    }
    var startSrc = 0, startEnc = 0, tmp, splitLen, rslt = [];

    while (startSrc != src.length){
        tmp = enc.substr(startEnc, len + 1);
        if (tmp.length > len) tmp = tmp.replace(/10*$/, "");
        startEnc += tmp.length;

        splitLen = tmp.replace(/0+/g, "").length;
        rslt.push(src.substr(startSrc, splitLen));
        startSrc += splitLen;
    }
    return rslt;
}
ダブルクリックの取得 (Nested Flatten)
JavaScript with jQuery on HTML
1
2
3
$(document).dblclick(function(ev){
    alert("x:"+ ev.clientX + "px, y:"+ ev.clientY + "px");
});
ローテートシフト (Nested Flatten)
rotate_r(parseInt("0010001111101101",2), 1).toString(2)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//文字列を指定数倍する
if(!String.prototype.x){
    String.prototype.x = function(n){
        var result="";
        for(var i=0;i<n;i++){
            result += this;
        }
        return result;
    }
}
//指定された桁数まで文字を補う
function paddingLeft(str, d, c){
    var len  = str.toString().length;
    var x = d > len ? d - len : 0;
    
    return c.x(x) + str;
}

function rotate_r(n, count, size){
    size = size | 16;//デフォルトは、16ビットで処理
    var wk_bin = paddingLeft(n.toString(2), size, '0');
    var over = wk_bin.substr(-count);
    wk_bin = over + wk_bin.substr(0, wk_bin.length - count);
    return parseInt(wk_bin, 2);
}
17歳教 (Nested Flatten)
1
javascript:[17,'years','+','days','months','old',function(k,i,n,o,u,e){while(i=prompt(k,i))k=[this[0],this[1],this[2],e=(n-(u=new(Date)(i)).setFullYear(this[0]+u.getFullYear()))/864e5|0,this[3],this[5]+'\n'+this[0],this[1],this[2],e/o|0,this[4],this[2],e%o|0,this[3],this[5]].join('\40')}][6]('Birthday:','1964/09/25',new(Date),30.437)
自分自身を表示する (Nested Flatten)
1
javascript:eval(_='(u=unescape)("javascript:eval(_=%"+27)+_+u("%"+"27)")')

関数オブジェクト.toString でソースが返ってくるので…

1
2
3
(function () {
    alert("(" + arguments.callee + ")()");
})()
エレベータの制御(基本編) (Nested Flatten)
#8319と同じアプローチで。
主にプログラム作成の容易さについて効率化しました(笑)
総移動距離は最短になります。

階数表記は英国式(0Fが地階)です。
----実行結果----
4F[7->4] -> 0F. (Round: 26)
4F[4->1] -> 0F. (Round: 52)
4F[1->0] -> 3F[11->9] -> 0F. (Round: 83)
3F[9->6] -> 0F. (Round: 105)
3F[6->3] -> 0F. (Round: 127)
3F[3->0] -> 0F. (Round: 149)
2F[3->0] -> 0F. (Round: 167)
1F[7->4] -> 0F. (Round: 181)
1F[4->1] -> 0F. (Round: 195)
1F[1->0] -> 0F. (Round: 209)
Finish.
        Total time: 209
        Total move: 52
        Max wait:   174
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
function log(str, lineContinue) {
    // for Rhino
    java.lang.System.out.print(str);
    if (!lineContinue) java.lang.System.out.println();
}

function Elevator(capacity, t1, t2) {
    this.capacity = capacity;
    this.t1 = t1;
    this.t2 = t2;
    this.init([]);
}

Elevator.prototype = {
    simulate: function (data) {
        this.init(data);
        var c;
        while (c = this.callingFrom()) {
            this.upTo(c);
            while (this.floor != 0) this.down();
        }
        this.printResult();
    },
    printResult: function () {
        log("Finish.");
        log("\tTotal time: " + this.round);
        log("\tTotal move: " + this.move);
        log("\tMax wait:   " + Math.max.apply(null, this.waitTime));
    }, 
    init: function (data) {
        this.floor = 0; // 英国式
        this.count = 0;
        this.round = 0;
        this.move = 0;
        this.waitTime = [];
        for(var i=0,n=data.length+1;i<n;i++) this.waitTime[i]=0;
        this.data = [0].concat(data);
    },
    upTo: function (f) {
        this.round += this.t1 * (f - this.floor);
        this.move += (f - this.floor);
        this.aliveAt(f);
    },
    down: function () {
        this.round += this.t1;
        this.move++;
        this.aliveAt(this.floor-1);
    },
    aliveAt: function (f) {
        this.floor = f;
        if (this.floor == 0) {
            this.round += this.t2;
            this.count = 0;
            log("0F. (Round: " + this.round + ")");
        } else {
            var n = Math.min(this.capacity - this.count, this.data[f]);
            if (n != 0) {
                this.round += this.t2;
                this.data[f] -= n;
                this.count += n;
                if(this.waitTime[f]==0) this.waitTime[f] = this.round;
                log(f + "F[" + (this.data[f] + n) + "->" + this.data[f] + "] -> ", true);
            }
        }
    },
    callingFrom: function () {
        for (var f = this.data.length - 1; f > 0; f--)
            if (this.data[f] > 0) return f;
        return 0;
    }
}

if (arguments.length > 0) {
    new Elevator(arguments.shift()*1, arguments.shift()*1, arguments.shift()*1).simulate(arguments);
} else {
    new Elevator(3, 2, 5).simulate([7, 3, 11, 7]);
}
2次元ランダムウォーク (Nested Flatten)

div タグを使ってランダムウォークのアニメーションまで実現しました。

window.onloadに追加はイマイチなのは自覚していますが、その点でのブラウザ互換に凝る必要は無いと思ったので今回は簡単化してます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html PUBLIC "-W3CDTD XHTML 1.0 StrictEN"
"http:www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>どう書く?ランダムウォーク</title>
    <script type="text/javascript">
        var RandomWalk = {
            _msgId: "msg",
            _boxId: "walkbox",
            _step: 20,
            _time: 100,
            start: function() {
                var box = document.getElementById(RandomWalk._boxId);
                box.style.top = box.parentNode.offsetHeight / 2 + "px";
                box.style.left = box.parentNode.offsetWidth / 2 + "px";
                setInterval(RandomWalk.update, RandomWalk._time);
            },
            update: function(style) {
                var box = document.getElementById(RandomWalk._boxId);
                box.style.top = RandomWalk.next_pos(box.offsetTop, box.parentNode.offsetHeight);
                box.style.left = RandomWalk.next_pos(box.offsetLeft, box.parentNode.offsetWidth);
                RandomWalk.show_message(box);
            },
            show_message: function(box) {
                document.getElementById(RandomWalk._msgId).innerHTML = "top=" + box.style.top + ", left=" + box.style.left;
            },
            next_pos: function(pos, max) {
                var val = pos + RandomWalk._step / 2 - Math.random() * RandomWalk._step;
                if (val < 0) val = 0;
                if (val > max) val = max;
                return val + "px";
            }
        }
        window.onload = function(){ RandomWalk.start() };
    </script>
</head>
<body>
    <div style="border: 1px solid #0000FF; width: 300px; height: 300px;">
        <div id="walkbox" style="width: 5px; height: 5px; position: absolute; background-color: #66FF33;
            border: 1px solid #DDEEFF;">
        </div>
    </div>
    <div id="msg">
    </div>
</body>
</html>
道順を数える (Nested Flatten)

典型的な動的計画法(DP)の練習問題ですね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function Point(up, left) {
   this.up = up; this.left =left;
}
Point.U = new Point(true, false);
Point.L = new Point(false, true);
Point.UL = new Point(true, true);
Point.NON = new Point(false, false);

var points;
with(Point) {
   points = [
      [U, L,  L,  L],
      [U, UL, UL, UL],
      [U, L,  UL, U],
      [U, UL, U,  UL],
      [U, UL, UL, UL]
   ];
}
function countRoute(points) {
   var count_table = new Array(points[0].lenth);
   count_table[0] = 1;

   for (var i=0, n=points.length; i<n; i++) {
      var row = points[i];
      for (var j=0, m=row.length; j<m; j++) {
         var p = row[j];
         count_table[j] = (p.up && count_table[j] || 0) + (p.left && count_table[j-1] || 0);
      }
   }
   return count_table[count_table.length-1];
}
alert(countRoute(points));
next >>

Index

Feed

Other

Link

Pathtraq

loading...