SHOEISHA iD

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

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

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

特集記事

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

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

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

レベル4:剰余を使わずに処理を行う

 レベル4では、新たに「%」が禁止されて、剰余が利用できなくなります。というわけで剰余を使わずに、3の倍数、5の倍数を判定しなければなりません。なかなか大変です。さすが、ダンジョンの最奥です。というわけで、その解き方を示していきます。

配列を使って文字列を結合

 それでは、まずは最も簡単な方法です。文字列を、配列を利用して結合して、答えの一覧を作成します。これは、シンプルなコードなので、実際に見てもらった方が分かりやすいでしょう。というわけで、以下をご覧ください。

配列を使って文字列を結合(35文字)
Array(8).join("300102100120100")[i]
配列を使って文字列を結合(数値を文字列に変換:33文字)
Array(8).join(300102100120100)[i]

 要素数8の「空の配列」を作り、「"300102100120100"」を間に挟んで結合しています。なかなかうまいやり方です。

小数点の数で判定1 split

 ある値で割った場合、小数点があれば割り切れておらず、小数点がなければ割り切れています。そこで、小数点の数を数えることで、判定を行います。処理としては、文字列として結合して、「.」の位置で「split」を使って分割します。

小数点の数で判定1 split(36文字)
4-(""+i/3+i/5+i/5).split(".").length

小数点の数で判定2 正規表現

 小数点が存在するかどうかは、正規表現でも判定できます。というわけで、その方法を示します。

小数点の数で判定2 正規表現(33文字)
3-/\./.test(i/3)-/\./.test(i/5)*2

number.toStringを使う

 除算の代わりに、進数変換を利用します。「number.toString([radix])」で、「radix」で指定した進数の文字列に変換できます。この仕様を使い「(14).toString(3)」とすれば「"112"」が得られます。「(15).toString(3)」ならば「"120"」が得られます。

 そこで、「"120".slice(-1)」とすれば「"0"」という末尾の文字列が得られます。3進数で末尾の値が「0」の場合は、3で割り切れます。この方法は、3や5で剰余を求める計算の代わりに使えます。以下、コードです。

number.toStringを使う(63文字)
"322"[i.toString(3).slice(-1)]-"02222"[i.toString(5).slice(-1)]

 15進数にしない理由は、文字列を数値に戻す場合に、「parseInt("文字列", 桁数)」と、「,」を使わないといけないからです。「,」は禁止文字なので、そのまま数値として利用できる3や5を使って計算しています。

倍数を引く

 以降は、計算的手法で答えを求めていきます。まずは、除算後、整数化して倍数を作成します。「i-parseInt(i/3)*3」のように計算することで「0,1,2,0,1,2,…」という剰余と同じ値が取れます。それでは、コードを見ていきましょう。

倍数を引く(39文字)
"3001021001201000"[i-parseInt(i/15)*15]

 シンプルな方法で剰余の代わりが得られます。

割り切れるか確認

 「parseInt」と「Boolean」を使い、割り切れるかを確認します。「Boolean(i/3-parseInt(i/3)」で、割り切れるときは「0」となり「false」が得られます。それ以外では少数点以下が発生して「0以外」になり「true」になります。それでは、コードを見ていきましょう。

倍数を引く(57文字)
3-Boolean(i/3-parseInt(i/3))-Boolean(i/5-parseInt(i/5))*2

割り切れる位置を検出

 「parseInt」を使い、割り切れる位置を検出します。「parseInt(i/3)-parseInt((i-1)/3)」で、割り切れる場合のみ「1」になります。それ以外は「0」になります。以下、コードです。

倍数を引く(67文字)
parseInt(i/3)-parseInt((i-1)/3)+(parseInt(i/5)-parseInt((i-1)/5))*2

おわりに

 記事は以上です。同じ処理を行うのにも、さまざまな方法があると気付いたのではないでしょうか。普段、プログラムを書く上では、こんなトリッキーなコードを書くことは、まずないと思います。しかし、たまにパズル的に遊ぶ上では、こういったコードを考えるのも楽しいです。また、今まで知らなかったプログラミング言語の仕様に気づくきっかけにもなります。

 今回は「FizzBuzz問題」を解決する、「FizzBuzzダンジョン」でしたが、「CodeIQ」では同系統の問題で「素数ダンジョン」も出題しています。「10~100」の間の素数を、1行で判定するという問題です。短く書いた場合は、20文字で書けることが確認されています。こういった遊びは、かたくなった頭をときほぐすのによいです。やわらかい頭になり、プログラムを書いてみてください。

参考資料

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

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

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

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

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

この記事をシェア

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

イベント

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

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

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

メールバックナンバー