SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

あなたはどこまで解き進められる?
「FizzBuzzダンジョン」でコードパズル

JavaScriptで遊ぶ、禁止文字つき制限コーディング

ダウンロード fizzbuzz_dungeon.zip (4.3 KB)

レベル3:演算子の制限がある中で計算

 レベル3で増えた禁止文字は、「!」「^」「~」「<」「>」「=」「Math」です。比較演算子を中心に、さまざまな計算方法が禁止されています。そのため、これまでとは違った発想で計算を行っていく必要があります。このレベルから、コードは非常に千差万別になります。それでは、実際の解き方を見ていきましょう。

関数やオブジェクトを利用

 最初の方法は、JavaScriptのビルトイン関数やオブジェクトを利用して解く方法です。

Boolean

 まず、使用するのは「Boolean」です。数値を真偽値にできます。「0」の場合は「false」、「0以外」の場合は「true」になります。こうして得た真偽値は、数値演算で「0」「1」に変換できます。そこから先は、これまでの処理の延長になります。それでは、実際のコードを見ていきましょう。

「Boolean」で計算(29文字)
3-Boolean(i%3)-Boolean(i%5)*2

 レベル2で出てきた「!(i%3)+!(i%5)*2」と違い、「3-」と3から引いています。これは、「!(i%3)+!(i%5)*2」のコードでは「!」と真偽の値を反転していましたが、「Boolean」は反転ではないためです。そのため、少しだけ違う計算になっています。

parseInt

 次は「parseInt」です。この関数は、小数点数を整数に変換することができます。ここで利用する操作は、以下のような操作です。

  • 「parseInt(1-i%3/3)」
    • i%3」が割り切れ、0になる場合
      • 「1-0/3」→「1-0」→「1」→整数化→「1」
    • i%3」が割り切れず、1になる場合
      • 「1-1/3」→「1-0.333」→「0.667」→整数化→「0」

 「1」未満なら、整数化する際に切り捨てられて、「0」になるという仕様を利用します。それでは、実際のコードを見てみましょう。

「parseInt」で計算(37文字)
parseInt(1-i%3/3)+parseInt(1-i%5/5)*2

isNaN

 次は「isNaN」です。この関数は、「NaN」(Not a Number、非数)の場合に「true」を、そうでない場合に「false」を戻します。

 この関数をどう使うかというと、「0」に関する演算で利用します。JavaScriptでは、例えば「0」に関する除算をした場合には、以下のような値が得られます。以下の「1」は、0以外の他の数値に置き換えてもよいです。

  • 「1/0」→「Infinity」
  • 「0/1」→「0」
  • 「0/0」→「NaN」

 この仕様を利用すると、「isNaN」で真偽値を得ることができます。「0/0」になるか否かで分岐するわけです。それではコードを見ていきましょう。

「isNaN」で計算1(31文字)
isNaN(0/(i%3))+isNaN(0/(i%5))*2
「isNaN」で計算2(27文字)
isNaN(i%3/0)+isNaN(i%5/0)*2

 上記の2つの計算は、「0/0」の得方に違いがあります。下のコードの方が若干短くなっています。

isFinite

 さて、「0」に関する除算では、「Infinity」が発生するか否かを利用する方法もあります。ここで利用するのは「isFinite」という関数です。この関数は、数値が有限値なら「true」、それ以外なら「false」を戻します。それではコードを見ていきましょう。

「isFinite」で計算2(39文字)
3-isFinite(1/(i%3))-isFinite(1/(i%5))*2

 「isNaN」の方が、若干短く書けます。それでは、次からは発想を変えて、これまでとはまったく違う方法で解いていきます。

配列を使う

 「何も計算しなくてよいよね。答えを羅列しておけば」という発想が、配列を使う方法です。この方法には2つの解があります。1つ目は、15周期で値が変化することを利用して、要素数15の配列を用意する方法です。2つ目は、3の倍数と5の倍数用に、3周期、5周期の配列を用意する方法です。

 これらのコードは、説明するよりもコードを見る方が分かりやすいので、以下のコードを見てください。

15周期で値が変化(数値と配列位置を合わせるために1を引く:41文字)
[0,0,1,0,2,1,0,0,1,2,0,1,0,0,3][(i-1)%15]
15周期で値が変化(1を引く代わりに要素の位置をずらす:37文字)
[3,0,0,1,0,2,1,0,0,1,2,0,1,0,0][i%15]
3周期と5周期の値を足す(29文字)
[1,0,0][i%3]+[2,0,0,0,0][i%5]

文字列を使う

 「配列を使う」の発展形です。取得する値がいずれも1桁であることから、文字列から特定の1文字を取得して、その値を数値として利用すればよいという発想です。JavaScriptでは、文字列を数値演算した場合、そのまま数値として計算されます(ただし、数値として利用可能な文字列でなければならない)。この仕様を利用して計算を行います。

 それではコードを掲載します。

文字列を使う1(30文字)
"300102100120100".charAt(i%15)

 「charAt」を使うことで、文字列の中から特定の1文字を取り出すことができます。

 さて、上記のコードはもっと短く書けます。JavaScriptでは「"abcd"[0]」のように、文字列に添え字を与えると、その位置の1文字を取得できます。それでは、この仕様を利用したコードを書いてみます。

文字列を使う2(23文字)
"300102100120100"[i%15]

 すいぶんすっきりとしました。次は文字列繋がりで、正規表現で判定する方法を紹介します。

正規表現を使う

 割り切れる場合、剰余は「0」になります。そのことを利用して、計算結果で「0」が得られれば真という正規表現の式を作り「test」を利用して判定します。これは、実際のコードを見ると一目瞭然なので、見てみましょう。

正規表現を使う(29文字)
/0/.test(i%3)+/0/.test(i%5)*2

 この先は、計算を使って解いていきます。シンプルですが、奥深い計算になっていきます。

剰余を使う

 剰余を連続して取ることで、「0」と「1」の値を得ます。「m%n%(n-1)...%2」の場合、「m」が「nの倍数+1」の時のみ「1」です。この性質を使い、「(i+1)」を使って、「1」と「0」に仕分けます。これは、図を見てもらった方が分かりやすいので、図を示します。

次々に剰余を取る
元の値   %5 %4 %3 %2
0 0 0 0 0
1 1 1 1 1
2 2 2 2 0
3 3 3 0 0
4 4 0 0 0

 それでは実際のコードを示しましょう。なかなか美しいコードになっています。

剰余を使う(25文字)
(i+1)%3%2+(i+1)%5%4%3%2*2

掛け算を使う

 剰余の次は掛け算です。ここでは「フェルマーの小定理」を利用します。

フェルマーの小定理

「p」を素数とし、「a」を「p」の倍数でない整数とする時に以下が成り立つ。

 

ap-1≡1 (mod p)

→「a」が「p」の倍数でないなら「1」になる。

→「a」が「p」の倍数なら「0」になる。

 コードを示します。こちらも、なかなか美しいコードになっています。

掛け算を使う(19文字)
3-i*i%3-i*i*i*i%5*2

 それでは、さらに難しいレベル4に入っていきましょう。

次のページ
レベル4:剰余を使わずに処理を行う

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/7546 2013/12/25 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー