CodeIQ MAGAZINECodeIQ MAGAZINE

大人気ダンジョンシリーズ!海のダンジョンの解説+最短コード発表 #javascript

2015.09.08 Category:CodeIQ問題解説・リーダーボード Tag: ,

  • 17
  • このエントリーをはてなブックマークに追加
level

大人気のダンジョンシリーズから、「海のダンジョン」問題LV1~LV2の解説記事です。

各レベルの成績ベスト20のコードは一見の価値あり!
by クロノス・クラウン合同会社 柳井政和

海のダンジョン

今回の ダンジョンは、以下のような問題でした。

【問題】

変数「q」として与えられる配列は2次元配列で、以下の6つの情報が入っています。

q=[
[ 3, 19], // 0艘目の船 [船の性能, 定員]
[ 5, 17], // 1艘目の船 [船の性能, 定員]
[13, 7] // 2艘目の船 [船の性能, 定員]
];

船は0艘目から2艘目までの3艘があります。それぞれの船の速度は「船の性能 / 定員」で求めることができます。この値が最も大きな船以外は、モンスターに襲われて食べられます。

あなたは、船の速度が最も大きな船の番号の数値を、変数「r」に格納してください。

ただし、船の性能と定員には、特殊な条件があります。船の性能が3以下の場合は、その船は沈みます。つまり速度は0です。また、定員が3名以下の船は、船を操る人がいないので出航できません。つまり速度は0です。

以下、例を示します。

例1

q=[
[ 3, 19], // 0艘目の船 [船の性能, 定員]
[ 5, 17], // 1艘目の船 [船の性能, 定員]
[13, 7] // 2艘目の船 [船の性能, 定員]
];

の場合の、各船の速度。

0艘目:「船の性能」が3で、3以下なので速度は0。
1艘目:「船の性能 / 定員」は、「5 / 17」で速度は0.29411764705882354。
2艘目:「船の性能 / 定員」は、「13 / 7」で速度は1.8571428571428572。

最も速度が速い船は2艘目なので、変数「r」に「2」を格納する。

例2

q=[
[13, 5], // 0艘目の船 [船の性能, 定員]
[19, 2], // 1艘目の船 [船の性能, 定員]
[ 7, 11] // 2艘目の船 [船の性能, 定員]
];

の場合の、各船の速度。

0艘目:「船の性能 / 定員」は、「13 / 5」で速度は2.6。
1艘目:「定員」が2で、3以下なので速度は0。
2艘目:「船の性能 / 定員」は、「7 / 11」で速度は0.6363636363636364。

最も速度が速い船は0艘目なので、変数「r」に「0」を格納する。

【問題のコード】

function yourCode() {
    // windowおよびそのプロパティのいくつかを自動ノックアウト
    /* @knockoutWindow */

    // 疑似乱数
    var rnd = (function() {
        var z = 123456789, x = z;
        return function(){return(x=(x*z+z)&0x7FFFFFFF)>>16}
    })();

    // 問題生成
    var q = (function() {
        var arr = [];
        for (var i = 0; i < 1024; i ++) {
            var p = [2, 19, 3, 17, 5, 13, 7, 11];
            var a = [
             [+p.splice(rnd()%6, 1), +p.splice(rnd()%6, 1)]
            ,[+p.splice(rnd()%5, 1), +p.splice(rnd()%5, 1)]
            ,[+p.splice(rnd()%4, 1), +p.splice(rnd()%3, 1)]
            ];
            arr.push(a);
        }
        return arr;
    })();

    // ★問題のコード
    var arr = [];
    for (var i = 0; i < q.length; i ++) {
        arr.push(
            (function(q) {
                var $, jQuery, yourCode, arr, i, rnd;
                arguments.callee = null;

                // 答えを変数「r」に入れて戻す
                var r = 0;
                【 入力欄(複数行可能) 】
                return r;
            })(q[i])
        );
    }
    return arr;
}

この問題は、レベルごとに禁止事項が増えていきます。そのポイントと、解答コードを、以下に掲載します。

レベル1解説

レベル1の禁止文字は、「 jQuery $ \ eval this with window top parent self frames document Function constructor repeat caller prototype =>」です。

基本的に「eval」関連を禁止しています。それ以外は大きな制限はありません。

今回の問題は、べたな条件分岐だけで解くことが出来ます。以下、基本的なコードを示し、他の解き方も紹介します。

解き方1)基本的なコード

まずは、基本的なコードを示します。

// 177文字
var max = 0;
for (var i = 0; i < 3; i ++) {
    var speed = q[i][0] / q[i][1];
    if (q[i][0] <= 3 || q[i][1] <= 3) {
        speed = 0;
    }
    if (speed > max) {
        r = i;
        max = speed;
    }
}

最初に、船の速度を計算します。次に、船の性能「q[i][0]」と、定員「q[i][1]」が3以下であるかを判定し、条件を満たす場合は速度を0にします。

最後に、速度が最大なら、変数「max」を入れ替え、その船の番号を変数「r」に格納します。この方法で、問題を解くことが可能です。

上記のコードを、ざっくりと短くすると以下のようになります。

// 63文字
for(m=i=0;p=q[i];i++)(s=p[0]>3&&p[1]>3&&p[0]/p[1])>m&&(r=i,m=s)
// 60文字
for(m=i=-1;p=q[++i];a>3&b>3&a/b>m&&(r=i,m=a/b))a=p[0],b=p[1]
// 56文字
for(m=i=-1;p=q[++i];p>3&b>3&p/b>m&&(r=i,m=p/b))b=p.pop()

最後のコードは、要素数1の配列をキャストすると、そのまま中身の値になる性質を使ったものです。

「[3,5]」のような配列を「b=p.pop()」で取り出すと、変数「p」の中身は「[3]」になります。この配列を数値演算すると「3」になります。

解き方2)配列オブジェクトの関数

配列オブジェクトの関数を使った解き方もあります。「forEach」「map」「filter」「reduce」などを使ったコードが送られてきました。その中から、文字数の少ない「map」を使って書いてみます。

速度が最大の船は、indexOfで取り出してみます。

// 119文字
q = q.map(function(x) {
    a = x[0];
    b = x[1];
    return a > 3 && b > 3 && a / b;
});
r = q.indexOf(Math.max.apply(0, q));

「indexOf」は、引数の値が、配列のどの位置にあるのかを探索する関数です。「Math.max.apply(0, q)」で、配列「q」の最大値を取得して、「indexOf」の引数にしています。

上記のコードを、ざっくりと短くすると以下のようになります。

// 88文字
q=q.map(function(x){a=x[0];b=x[1];return a>3&b>3&&a/b})
r=q.indexOf(Math.max.apply(0,q))

レベル2解説

レベル2では新たに、「< > /」の禁止文字が追加されています。これらは、3以下の判定と、速度の計算を禁止するものです。最大値の確認は、レベル1で示したindexOfでも可能です。

これらの禁止文字を避けるには、いくつかの方法があります。3以下の判定と、速度の計算に分けてリストにします。

● 3以下の判定

・&演算子を使う。
・剰余を使う。
・Math.maxを使う。
・引き算でマイナスになるか確認。

● 速度の計算

・掛け算と引き算を使う。
・Math.atan2を使う。
・Math.powを使う。
・Math.exp Math.logを使う。

ほとんどの場合は、このいずれかの方法、あるいはその組み合わせや変形でした。以下、それぞれの例を示していきます。

方法1)&演算子を使う、掛け算と引き算を使う

2つの例を示します。まずは1つ目です。

// 168文字
A = 0;
B = 1;
for (i = 0; p = q[i]; i ++) {
    a = p[0];
    b = p[1];
    if (a & 28 && b & 28) {
        if (Math.sign(a * B - A * b) == 1) {
            r = i;
            A = a;
            B = b;
        }
    }
}

「28」は2進数で「11100」。「& 28」の計算を行うことで、0, 1, 2の場合は「0」になります。船の性能、定員に使われる数値の最大は「19」です(生成コードを確認してください)。この19は、2進数で「10011」なので、「0」にはなりません。

次に、船の速度の比較を説明します。

a, bを現在の値、A, Bを最大値の時の値とした時、「a / b > A / B」の式は、「a * B > A * b」→「a * B - A * b > 0」に変形可能です。そして、「> 0」の判定が真の時、つまり左辺が正の数なら条件を満たします。そこで、「Math.sign」で正負の符合を取り出し、確認しています。

次に、2つ目の例を示します。

// 158文字
A = 0;
B = 1;
for (i = 0; p = q[i]; i ++) {
    a = p[0];
    b = p[1];
    if (a & ~3 && b & ~3) {
        if (A * b - B * a & 512) {
            r = i;
            A = a;
            B = b;
        }
    }
}

「~3」は「-4」です。「-4」は2進数で「1111 1111 1111 1111 1111 1111 1111 1100」。「& ~3」で、0, 1, 2は「0」になります。

「512」は2進数で「10 0000 0000」です。「A * b - B * a」の正の場合の最大値は「19 * 17 - 2 * 3」で「317」、負の場合の最小値は「-317」です。

「317」は2進数で(1 0011 1101)、「-317」は2進数で「1111 1111 1111 1111 1111 1110 1100 0011」です。

 512  0000 0000 0000 0000 0000 0010 0000 0000
 317  0000 0000 0000 0000 0000 0001 0011 1101
-317  1111 1111 1111 1111 1111 1110 1100 0011

そのため、「A * b - B * a」が負の場合のみ、「& 512」が0以外の数値になります。

方法2)剰余を使う、Math.atan2を使う

「Math.atan2」を使うのが、おそらく最も簡単な方法です。

「Math.atan2」は、引数の比率でのアークタンジェントを返す関数です。ちょっと分かりにくいですね。

アークタンジェントは、タンジェントの逆関数です。これでも、分かりにくいですね。もう少し、詳しい説明をした方がよさそうです。

タンジェントは、角度Aを引数にして、以下の図のy/xを求めます。

アークタンジェントは、引数yとxから求める比率y/xを元にして、角度Aを求めます。以下、例を示します。

// yが1、xが1の場合、Math.PI / 4(=45度)になる
console.log(Math.atan2(1, 1) - Math.PI / 4);  // 「0」と出力

// yが1、xが√3の場合、約 Math.PI / 6(=30度)になる
var n = Math.atan2(1, Math.sqrt(3)) - (Math.PI / 6)
console.log(n.toFixed(20)); // 「0.00000000000000011102」と出力

このアークタンジェントの計算を使えば、自動車のタコメーターのように、速度を角度として比較できるようになります。

というわけで、実際にコードを書いてみます。

// 130文字
q = q.map(function(x) {
    a = x[0];
    b = x[1];
    return 6 % a && 6 % b && Math.atan2(a, b);
});
r = q.indexOf(Math.max.apply(0, q));

「6 % a」「6 % b」の部分は、3以下かを判定するコードです。船の性能、定員に使われる数値は、全て素数です(生成コードを確認してください)。そのため、「6 %」の計算を行い「0」になるのは、2, 3の場合のみです。

方法3)Math.maxを使う、Math.powを使う

「Math.max」で、3以下かを判定できます。

「Math.pow(n, -1)」で、除算の代わりになります。

// 170文字
q = q.map(function(x) {
    a = x[0];
    b = x[1];
    m = Math.max;
    p = Math.pow;
    return m(a, 3) != 3 && m(b, 3) != 3 && a * p(b, -1);
});
r = q.indexOf(Math.max.apply(0, q));

方法4)引き算でマイナスになるか確認、Math.exp Math.logを使う

「Math.log(x)」は、xの自然対数(底はE)を返します。

「Math.exp(x)」は、Exを得る関数です。

「Math.log(-Math.exp(x))」とすることで、除算の代わりになります。

// 188文字
q = q.map(function(x) {
    a = x[0];
    b = x[1];
    s = Math.sign;
    l = Math.log;
    e = Math.exp;
    return s(a - 4) == 1 && s(b - 4) == 1 && a * e(-l(b));
});
r = q.indexOf(Math.max.apply(0, q));

以下に、もう一つの解法も示します。

// 170文字
q = q.map(function(x) {
    a = x[0];
    b = x[1];
    l = Math.log;
    e = Math.exp;
    return e(a - 4) | 0 && e(b - 4) | 0 && a * e(-l(b));
});
r = q.indexOf(Math.max.apply(0, q));

「Math.exp(x)」は、Exを得る関数です。そこにマイナスの引数xを与えると、xの絶対値で、1/Exの計算を行うことになります。これは1より小さくなります。この値を「| 0」で整数化すると0になります。

代表的な解法は、こういった感じでした。

それでは以下、上位者のコードを紹介していきます。

レベル1の上位者コード(20位~11位)

以下、20位から11位の方のコードです。いろんなコードが見たいと思いますので、同じ方のコードでも、順位に当てはめて掲載しています。

20位のコード(76文字)

// soilblue2000 様
d=0;for(i=0;i<3;i++){a=q[i][0];b=q[i][1];m=a<4||b<4?0:a/b;if(m>d){r=i;d=m;}}

19位のコード(75文字)

// donguri 様
a=0;for(j=3;j--;){b=q[i,j];t=(b[0]<4|b[1]<4)?0:b[0]/b[1];if(a<t){a=t;r=j;}}

18位のコード(73文字)

// suppy193 様
x=0
for(i in q)if((v=((p=q[+i][0])>3&&(c=q[+i][1])>3)?p/c:0)>x){r=+i
x=v}

// パパンダ 様
for(i=m=0;i<3;i++){a=q[i][0];b=q[i][1];k=a/b;if(a>3&&b>3&&k>m){r=i;m=k;}}

17位のコード(72文字)

// まったし 様
s=0;for(i in q){if((a=q[i][0])<4||(b=q[i][1])<4)a=0;if(s<a/b)r=+i,s=a/b}

16位のコード(71文字)

// YU2045 様
for(i=m=0;i<3;i++)a=q[i][0],b=q[i][1],m<((a<4||b<4)?0:a/b)&&(m=a/b,r=i)

15位のコード(69文字)

// ずごご 様
for(a=i=0;i<3;i++)if((b=(c=q[i][0])<4||(d=q[i][1])<4?0:c/d)>a)a=b,r=i

14位のコード(68文字)

// ciel 様
for(i=m=0;3>i;i++)if(x=q[i][0],y=q[i][1],z=(x>3&y>3)*x/y,z>m)m=z,r=i

// えちごやえちぜん 様
for(j=i=0;i<3;i++){s=q[i][0];p=q[i][1];if(s>3&&p>3&&s/p>j)r=i,j=s/p}

13位のコード(66文字)

// iehn 様
for(a=i=-1;i++^2;r=b>3&c>3&a<d?(a=d,i):r)d=(b=q[i][0])/(c=q[i][1])

// なおゆら 様
t=i=0;for(s of q)t<(v=(s[0]<4||s[1]<4)?0:s[0]/s[1])&&(r=i,t=v),++i

// Mattsun 様
t=0;for(i=3;i--;)if((a=q[i],s=a[0]/a[1])>t&&a[0]>3&&a[1]>3)t=s,r=i

12位のコード(65文字)

// todaemon 様
i=m=0;for(s of q){(t=s[0]>3&&s[1]>3&&s[0]/s[1])>m&&(r=i,m=t);i++}

11位のコード(64文字)

// sham_shell 様
for(i in q)r=q[r]<(q[i]=(a=q[i][0])<4||(b=q[i][1])<4?0:a/b)?+i:r

// y azshe 様
t=i=0;for(a of q)s=a[0]>4&&a[1]>4?a[0]/a[1]:0,s>t&&(r=i,t=s),++i

レベル1の上位者コード(10位~1位)

 以下、10位から1位の方のコードです。いろんなコードが見たいと思いますので、同じ方のコードでも、順位に当てはめて掲載しています。

10位のコード(63文字)

// Theodore 様
s=i=0;for(p of q)d=p[0]/p[1],p[0]>3&&p[1]>3&&d>s&&(s=d,r=i),++i

// しゃろ 様
for(m=i=0;s=q[i];i++)v=s[0]>3&s[1]>3?s[0]/s[1]:0,v>m&&(r=i,m=v)

// おじけん 様
i=v=0;for(p of q)a=p[0],b=p[1],a>3&&b>3&&a/b>v&&(v=a/b,r=i),++i

// todaemon 様
i=m=0;for(s of q)(t=s[0]>3&&s[1]>3&&s[0]/s[1])>m&&(r=i,m=t),i++

// Mattsun 様
for(t=i=0;a=q[i];i++)if(a[0]>3&&a[1]>3&&(s=a[0]/a[1])>t)t=s,r=i

9位のコード(62文字)

// みけCAT 様
s=0;for(i in q)z=q[i][0],y=q[i][1],z>3&y>3&s<z/y&&(s=z/y,r=+i)

8位のコード(61文字)

// gmk 様
i=c=0;for(t of q)t[0]>3&t[1]>3&(a=t[0]/t[1])>c&&(r=i,c=a),i++

// rotary-o 様
q.map({f(a,j){a[0]>3&a[1]>3?i>(v=a[0]/a[1])||(i=v,r=j):0}}.f)

// epuboro 様
n=m=0;for(a of q)z=a[0]/a[1],a[0]>3&a[1]>3&m<z&&(r=n,m=z),n++

// epuboro 様
n=m=0;for(a of q)z=a[0]/a[1],a[0]>3&a[1]>3&m<z&&(r=n,m=z),n++

// Theodore 様
s=i=0;for(p of q)d=p[0]/p[1],p[0]>3&p[1]>3&d>s&&(s=d,r=i),++i

7位のコード(60文字)

// Azicore 様
k=0;for(s of q)t=s[0]>3&s[1]>3&&s[0]/s[1],i>t||(r=k,i=t),k++

6位のコード(59文字)

// rotary-o 様
for(j=3;a=q[--j];a[0]>3&a[1]>3?i>v||(i=v,r=j):0)v=a[0]/a[1]

// みけCAT 様
j=0;for(d of q)z=d[0],y=d[1],z<4|y<4|z/y<i||(i=z/y,r=j),j++

// haii 様
j=0;for(p of q)p[0]<4|p[1]<4|(n=p[0]/p[1])<i||(i=n,r=j),j++

5位のコード(58文字)

// rotary-o 様
for(j=3;a=q[--j];i>v||(i=v,r=j))v=a[0]>3&a[1]>3&&a[0]/a[1]

4位のコード(57文字)

// tails 様
for(e of q)a=e.pop(),x=e>3&a>3&&e/a,x<i||(r=q|=0,i=x),++q

// rotary-o 様
for(j=3;a=q[--j];v<i||(i=v,r=j))v=~~a[3%a[0]%a[1]-3]/a[1]

// kura07 様
for(n=3;a=q[--n];b<4|c<4|i>b/c||(i=b/c,r=n))b=a[0],c=a[1]

3位のコード(56文字)

// tails 様
for(e of q)a=e.pop(++q),x=e>3&a>3&&e/a,x<i||(r=q|=0,i=x)

2位のコード(55文字)

// tails 様
for(e of q)a=e.pop(++q),x=e>3&a>3&&e/a/9,x<i?0:r=q|=i=x

1位のコード(53文字)

// rotary-o 様
for(j=3;a=q[--j];3%a%b<3|a/b<i||(i=a/b,r=j))b=a.pop()

レベル2の上位者コード(20位~11位)

以下、20位から11位の方のコードです。いろんなコードが見たいと思いますので、同じ方のコードでも、順位に当てはめて掲載しています。

20位のコード(95文字)

// epuboro 様
n=m=0;p=Math.pow;for(a of q)x=a[0],y=a[1],(x&~3)*(y&~3)*!~~(m*y*p(x,-1))&&(r=n,m=x*p(y,-1)),n++

19位のコード(94文字)

// おじけん 様
i=v=0;for(p of q)a=p[0],b=p[1],6%a!=0&&6%b!=0&&Math.max(c=Math.atan2(a,b),v)!=v&&(v=c,r=i),++i

18位のコード(93文字)

// まったし 様
s=0;for(i in q)if((n=Math.min)(s,g=Math.atan2((n(a=q[i][0],b=q[i][1],4)==4)*a,b))==s)r=+i,s=g

17位のコード(92文字)

// rotary-o 様
for(j=3;a=q[--j];v==(i=Math.max(i||0,v))?r=j:0)v=a[0]*.3|0&&a[1]*.3|0&&Math.atan2(a[0],a[1])

16位のコード(91文字)

// しゃろ 様
for(a=Math,m=i=0;s=q[i];i++)v=s[0]&~3&&s[1]&~3?a.atan2(s[0],s[1]):0,a.max(v-m,0)&&(r=i,m=v)

// Mattsun 様
t=0;for(i=3;i--;)if(a=q[i],a[0]&28&&a[1]&28&&Math.max(s=Math.atan2(a[0],a[1]),t)==s)t=s,r=i

15位のコード(90文字)

// iehn 様
for(a=i=-1;i++^2;r=b&12&&c&28&&Math.min(a,d)-d?(a=d,i):r)d=Math.atan2(b=q[i][0],c=q[i][1])

// haii 様
j=0;for(p of q)(p[0]-4+q+(p[1]-4)+((n=Math.atan2(p[0],p[1]))-i)).match('-')||(i=n,r=j),j++

// Theodore 様
s=i=0;m=Math;for(p of q)d=m.atan2(p[0],p[1]),(p[0]*p[1]%6&3)*m.sign(d-s)==1&&(s=d,r=i),++i

14位のコード(89文字)

// gmk 様
i=c=0;for(t of q)t[0]&28&&t[1]&28&&Math.max((a=Math.atan2(t[0],t[1]))-c,0)&&(r=i,c=a),i++

// rotary-o 様
for(j=3;a=q[--j];r=i-v?r:j)i=Math.max(i||0,v=a[0]*.3|0&&a[1]*.3|0&&Math.atan2(a[0],a[1]))

13位のコード(88文字)

// Mattsun 様
for(t=i=0;a=q[i];i++)if(a[0]&28&&a[1]&28&&Math.max(s=Math.atan2(a[0],a[1]),t)==s)t=s,r=i

12位のコード(85文字)

// Theodore 様
s=i=0;m=Math;for(p of q)d=m.atan2(a=p[0],b=p[1]),m.sign(d-s)*a*b%6%4-1||(s=d,r=i),++i

// y azshe 様
t=i=0;for(a of q)s=a[0]&28&&a[1]&28?Math.atan2(a[0],a[1]):0,q[s-t-1|0]&&(r=i,t=s),++i

11位のコード(81文字)

// gmk 様
i=c=0;for(t of q)t[0]&28&&t[1]&28&&(a=Math.atan2(t[0],t[1]))-c+1|0&&(r=i,c=a),i++

レベル2の上位者コード(10位~1位)

以下、10位から1位の方のコードです。いろんなコードが見たいと思いますので、同じ方のコードでも、順位に当てはめて掲載しています。

10位のコード(80文字)

// rotary-o 様
for(j=3;a=q[--j];v%i!=v&&(i=v,r=j))v=a[0]*.3|0&&a[1]*.3|0&&Math.atan2(a[0],a[1])

// Azicore 様
k=-1;for(s of q)t=Math.atan2(s[0]*s[1]%6%4==1&&s[0],s[1]),++k+[i-t]|0||(r=k,i=t)

9位のコード(78文字)

// みけCAT 様
s=0,t=1;for(i in q)z=q[i][0],y=q[i][1],z&~3&&y&~3&&s*y-z*t&512&&(s=z,t=y,r=+i)

// gmk 様
i=c=0;for(t of q)6%t[0]*6%t[1]&&(a=Math.atan2(t[0],t[1]))-c+1|0&&(r=i,c=a),i++

8位のコード(76文字)

// gmk 様
i=c=0;for(t of q)(a=Math.atan2(v=t[0],w=t[1]))-c+1|0&&6%v*6%w&&(r=i,c=a),i++

7位のコード(75文字)

// haii 様
c=d=i=0;for(p of q)Math.min(a=p[0],b=p[1],a*d-b*c+4,4)-4||(c=a,d=b,r=i),i++

6位のコード(74文字)

// rotary-o 様
for(j=3;a=q[--j];v%i!=v&&(i=v,r=j))v=6%a[0]&&6%a[1]&&Math.atan2(a[0],a[1])

5位のコード(73文字)

// rotary-o 様
for(j=3;a=q[--j];v%i!=v&&(i=v,r=j))v=6%a[0]*6%a[1]&&Math.atan2(a[0],a[1])

// tails 様
for(e of q)x=Math.atan2(a=e.pop(++q),e&28&&a&28&&e),x-i+1|0||(r=q|=0,i=x)

4位のコード(72文字)

// rotary-o 様
for(j=3;a=q[--j];v%i!=v&&(i=v,r=j))v=Math.atan2(~~a[3%a[0]%a[1]-3],a[1])

3位のコード(71文字)

// rotary-o 様
for(i=j=3;a=q[--j];v%i==v&&(i=v,r=j))v=Math.atan2(b=a.pop(),a[3%a%b-3])

// みけCAT 様
j=0;for(d of q)z=d[0],y=d[1],z*i-q*y&512||z&~3&&y&~3&&(q=z,i=y,r=j),j++

// kura07 様
for(n=3;a=q[--n];6%b*6%c&&t%i!=t&&(i=t,r=n))t=Math.atan2(b=a[0],c=a[1])

2位のコード(70文字)

// tails 様
for(e of q)x=Math.atan2(a=e.pop(++q),a&28&&e&28&&e),x-i|0?0:r=q|=i=x-1

1位のコード(68文字)

// rotary-o 様
for(j=3;a=q[--j];v%i!=v&&(i=v,r=j))v=Math.pow(b=a.pop(),4%a%b*2-9)*a

■ 文字数の分布

今回の問題の文字数の分布をまとめておきます。

レベル1では、120文字以内が多く、80文字を切った辺りから上位者争いという感じでした。

平均は104.14文字。90文字を切っていれば、かなりよい感じかと思います。

レベル2では、120文字以内は上位を争っている方々だという印象でした。

平均は125.9文字。こちらは、100文字を切っていれば、かなりの腕前だと思います。

CodeIQ運営事務局より

柳井さん、ありがとうございました!
現在、柳井さんの最新問題が出題中です。
ぜひ挑戦してみてくださいね!

  • 17
  • このエントリーをはてなブックマークに追加

■この記事を書いた人

avatar

クロノス・クラウン合同会社 柳井政和

クロノス・クラウン合同会社 代表。ゲームやアプリを作ったり、プログラムを 書いたり、文章を書いたり、絵を描いたり。『マンガでわかるJavaScript』、 CodeIQの問題を解説付きでまとめた『プログラマのためのコードパズル~ JavaScriptで挑むコードゴルフとアルゴリズム』執筆。 twitter: @ruten Web Site: http://crocro.com/

■関連記事

【謎解きプログラム】解像度に対応せよ!【dpi】解答と解説... 【謎解きプログラム】解像度に対応せよ!【dpi】 本問題は、「解像度に対応せよ!」というテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されてい...
【選択式問題】JavaScript検定RPG Array編 問題解説 #javascript... 今回の問題 今回の『JavaScript検定RPG』は『Array編』ということで、JavaScript のArrayについての問題が出題されました。 それでは以下、各問題とその解答を見ていきましょう。 問題1 配列を作る方法として適切でないのはどれ? new Array(0, 1, 2)...
【選択式問題】JavaScript検定RPG String編 問題解説 #javascript... 今回の問題 今回の『JavaScript検定RPG』は『String編』ということで、JavaScriptのStringについての問題が出題されました。 それでは以下、各問題とその解答を見ていきましょう。 問題1 文字列の特定の位置の文字を得る方法として、適切でないのはどれ? "ねこみみ"...
【選択式問題】JavaScript検定RPG ループ処理編 問題解説 #javascript... 今回の問題 今回の『JavaScript検定RPG』は『ループ処理編』ということで、JavaScript のループ処理についての問題が出題されました。 それでは以下、各問題とその解答を見ていきましょう。 問題1 for (var i = 0, s = ""; i < 5; i++) s +=...
【選択式問題】JavaScript検定RPG 条件分岐編──問題解説 #javascript... 今回の問題 今回の『JavaScript検定RPG』は『条件分岐編』ということで、JavaScript の条件分岐についての問題が出題されました。 それでは以下、各問題とその解答を見ていきましょう。 問題1 ifのあとに書き、条件に一致しない場合の処理を行う構文は何? elf dwarf ...
大人気ダンジョンシリーズ!IQのダンジョンの解説+最短コード発表 #javascript... IQのダンジョン 今回の ダンジョンは、以下のような問題でした。 【問題】 標準入力から得られる値は「」のような文字列です。この文字列を、配列として解釈した配列の各要素には、36進数(0,1,2~,x,y,z)の数値を表す文字列が入っています。 この配列の各要素を、36進数の数字として解釈し...

今週のPickUPレポート

新着記事

週間ランキング

CodeIQとは

CodeIQ(コードアイキュー)とは、自分の実力を知りたいITエンジニア向けの、実務スキル評価サービスです。

CodeIQご利用にあたって
関連サイト
codeiq

リクルートグループサイトへ