作成者別アーカイブ: takamoto

逆FizzBuzz問題をオブジェクト指向(C++)で解く


Blogの生存報告がてら。

ちょっと旬の過ぎた話題ですが、逆FizzBuzz問題をC++で、自分なりにがんばってオブジェクト指向っぽく解いてみます。

逆FizzBuzz問題

FizzBuzzゲームは英語圏での定番飲み会用ゲームで、日本で言うナベアツゲームみたいなものです。

ルールは各人が1から順に数を言っていき、3の倍数のときには数字の代わりにFizz、5の倍数のときにはBuzz、3かつ5の倍数のときにはFizzBuzzを言うというものです。

具体的にはこうなります: 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, …

プログラミング界隈では初歩的なコーディング問題として、相手が本当にプログラミングができるのかどうかを知る問題として使われるそうです。(現場で本当に使われているのかは知りません。)

さて、逆FizzBuzz問題というのは、これに関連した問題の逆問題として定義されます。

まず、1からでなく適当な数字から始め、さらに数字を言わないFizzBuzz問題を考えます。

例えば25から始めるとすると、25はBuzz、26は飛ばす、27はFizz、28は飛ばす、29は飛ばす、30はFizzBuzz、… となり、この結果はBuzz, Fizz, FizzBuzz, … となります。

これの逆問題を考えます。つまり、FizzやBuzzやFizzBuzzの羅列でできた文字列が与えられたとき、結果がそれに一致するような数列を求めたい、それを逆FizzBuzz問題と定義します。

それだけだと答えが複数あるので、今回はその中で最小の数列の最も小さい数から始まるものを答えとしましょう。

具体的な問題例とその答えは以下のようになります。

  • “Fizz”なら3
  • “Fizz, Buzz”なら9,10 (3,4,5より短い)
  • “FizzBuzz”なら15
  • “FizzBuzz, Fizz”なら15, 16, 17, 18

より詳しくは元ネタを和訳されている以下のリンクを参照してください:
逆FizzBuzz問題 (Inverse FizzBuzz) – 猫とC#について書くmatarilloの雑記

オブジェクト指向で逆FizzBuzz問題

ここからプログラミングの話題。

先に挙げたリンク先(とさらにその先の英語原文)では、オブジェクト指向プログラミングがプログラマーに滅びをもたらす思想であると認定され、代わりに関数型プログラミングが広く認められた近未来で逆FizzBuzz問題を解くお話になっています。

まあ、オブジェクト指向が悪であるかどうかは議論を避けるとして、ここでは2016年になってもやっぱりオブジェクト指向は世の中を支配していた、そしてその世界で逆FizzBuzz問題もオブジェクト指向のノリで解く必要に迫られたらどうなるのかをやってみた、という内容になります。(そもそも私は関数型プログラミングをきちんと勉強していない人なので、善悪の議論ができません。)
言語は例によってC++11です。だいたい次のように決めておきます。

  • 出力は逆FizzBuzz問題の解の数列の範囲。例:”Fizz Buzz” → “[3,5]”
  • 入力が空文字のときは[0,0]を返す。
  • 解がないときは適当に文句を返す。

先にソースコードを書いてしまいましょう。
続きを読む


Togetter「#俺が見たクソコード選手権 まとめ」の補足


Togetterで先日まとめた「#俺が見たクソコード選手権 まとめ」についての話です。

Taken by nebulux76, Flickr

Taken by nebulux76, Flickr

そこそこ反響があったのですが、「書いてある中身がよくわからない」という反応もいくらかあったので、一部抜粋してちょっとだけ補足してみたいと思います。

なるべく書いた側の身になって考えてみたいと思います。

何かコメントで見当はずれなところがありましたらご指摘よろしくお願いします。私もいわゆるクソコードを書いてしまうことがよくあるので。


掃除機で同じ所を何度もかけるようなノリですね。過去に何があったんでしょうか。

一応、マルチスレッドの処理などを適当に書いてしまうと、代入した変数の値が適当なタイミングで勝手に書き変わってしまうことがあります。

もっとも、その場合でも変数にvolatile宣言をしておかないと最適化で取り除かれてしまいますが。


絶対に実行されないコード。適当な変数が定数になったとき、機械的に置換していくとこういう記述が出てくるおそれがあります。

普通のコンパイラならWarning出してくれるような?

続きを読む


「ガリレオ温度計」買ってきました。


先日、東急ハンズ渋谷店で気になっていたものをいくつか買ってきました。

本当は低温度差スターリングエンジンを探しに行ったのですが、そちらは今は置いてありませんでした。

東急ハンズ戦利品

今回の注目は左上の品。「ガリレオ温度計」です。浮きに温度が書いてあり、浮き沈みで温度を計るようになっています。

実験用とかではなく、完全なインテリア用です。

花にそえてみたの図

花にそえてみたの図

続きを読む


「クイックソートをHaskellで書くと5行、C++で書くと35行!」←いやそんなにかからないだろ


(この記事はC++メインの内容です。)

関数型言語のセンスも身につけておかないと、と思ってHaskellの簡単なお勉強をしようと思いました。

圏論のような背景や文法から把握するのもひとつのルートですが、まずは適当な例を見てみようと思ったわけです。
「関数型言語だとこんなことができる!」みたいな驚きがあったほうが楽しいですしね。

Taken by Robert Scarth, Flickr

Taken by Robert Scarth, Flickr

まずはHaskellでのクイックソートの実装例を探してみました。クイックソートというのはアルゴリズムの勉強を1からすると必ずと言っていいほど登場するほどのものですし、比較もできて面白そうです。

さて、「Haskell クイックソート」でGoogle検索にかけてみると、「C++だと35行のところがHaskellは5行で書ける」だの、「最も美しいコードのひとつ」だのとなかなか景気の良い記事が出てきます。

ところがもう少し読んでみると、「Haskellの5行クイックソートはクイックソートではない」みたいな議論がされているページがいくつか出てきます。

Togetterにいろいろな主張のまとめがありました。曰く、

「In-placeソートでないからだめ」「というか遅い」「いやHaskellに効率を求めてはいけない」「5行の例はPivotingをしていないのでだめ」「Pivotingはクイックソートの本質ではない」「メモリを抽象化していて扱えていないのでとても遅い」「Haskellでメモリの議論をするべきでないしIn-placeソートでなくてもよい」「Haskellでクイックソートをしっかり書きたいなら手続き型風に書くのが良い」

といった感じで、さっそく頭が痛くなってきました。

まあ今回はHaskellについては一旦置いておいて、その途中で出てきた「C++のクイックソートは35行」の部分についての話です。C++で普通に書いてももっと短くなっていいはずです。

結果から書きますと、普通に書いても9行くらいになりました。

続きを読む


マンデルブロー集合へ飛び込む


先日のマンデルブロー集合の10の200乗倍で作成したプログラムがあるので、今回はマンデルブロー集合の様々な地点へ飛び込んだ動画を作ってみました。

前回の記事を見ていない方はそちらからどうぞ:

[フラクタル] マンデルブロー集合 10の200乗倍への挑戦

今回訪れる地点は計5箇所です。どの点も拡大していく最中に集合全体と同じ形が現れます。フラクタルらしくて面白いと思います。

具体的には以下の点です。緑は前回の場所。それぞれ個性的な場所だと思います。

Mandelbrot Set with Circles (Picture from Wikimedia)

Mandelbrot Set with Circles (from Wikimedia)

この集合はフラクタルなので自己相似の図形ではあるのですが、ただ単純にどこでも同じ形を持っているわけではありません。拡大する場所を変えると景色が一変してしまいます。

肝心の動画はこちら。ニコニコ動画はこちら

続きを読む


C++11の新しい乱数の使い方おぼえがき


忘れた頃にふと必要になるので自分用にメモしておきます。

Taken by Matteo.Mazzoni, Flickr

Taken by Matteo.Mazzoni, Flickr

C++11には新しい乱数ライブラリが標準で用意されました。

もちろん従来の乱数rand()も使えますが、内部の実装が決まっていないのと、またその実装について様々な問題点が指摘されていることもあり、C++11ではより新しく使いやすい乱数が定義されたのでした。

これが int rand2(); みたいに定義されていれば使う側としては簡単なのですが、残念ながら使うにはもう少し長い構文が必要になります。

(何も考えず乱数を使いたい人にはかなりマニアックな話題だと思います。C++11の実装の話と乱数の話を行ったり来たりします。)

結論だけ書くと、以下のように乱数myrandを作ることができます。

#include <random>
#include <functional>
#include <ctime>

auto myrand = std::bind(std::uniform_int_distribution<int>(0, 99), std::mt19937(static_cast<unsigned int>(time(nullptr)));

例によってコンパイル時に-std=c++11 オプションをつけて下さい。

続きを読む


[お知らせ]blogのお引越しをします (追記:しました)


このblogページのお引越しをします。

ドメインを変更するだけですので、突然見れなくなったり中身が新規になったりするわけではありません。

今まで来てくださった方にも問題が起きないように注意しますが、変更中は何度か不安定になるかもしれません。よろしくお願いします。

引越しが終わりましたらまた連絡します。


追記: 引越しを完了しました。

旧URLは http://oniku64.dyndns.org/blog/ でしたが、

新URLは http://elephnote.com/blog/ となりました。

旧URLにアクセスしても転送されるので問題はありませんが、永久的にではありませんので、ブックマーク等している方がいましたらお手数ですが変更のほうよろしくお願いします。


現れては議論になるあの確率の問題を愚直にやってみた


今回の話題はこれです。

ジョーカーを除いたトランプ52枚の中から1枚のカードを抜き出し、
表を見ないで箱の中にしまった。
そして、残りのカードをよく切ってから3枚抜き出したところ、
3枚ともダイヤであった。
このとき、箱の中のカードがダイヤである確率はいくらか。
答えが1/4ってのは納得出来ない!
10/49だろ!!

定期的にあちこちで話題になる確率の問題です。

調べると2chまとめサイトなどでも話題にされていますし、考察しているブログなども多数見つかります。
Yahoo!知恵袋では早稲田大学の過去問だという方がいました。

論調もいろいろで、1/4だよ派と10/49だよ派だけに限らず、本文の解釈の仕方で違うだの、この問題は単純な確率の問題ではないだのと様々な意見が出されています。

実際には数学的にきちんと議論できて正解も出せるのですが、それでは納得できない人は大勢います。数式で考えるというのは抽象化のレベルが相当高いので、計算上はともかく問題文を本当に反映できているのか?という疑問が起きるのは不思議なことではありません。

あれこれ議論する前に、実際にやってみればいいんですね。

今回はその結果の話と、結果の「正しさ」の扱いについて少し書いておきます。

続きを読む


「抜き打ちテストのパラドックス」を撃破する


「抜き打ちテストのパラドックス」という有名なパラドックスがあるのですが、たいていどの記事でもパラドックスの紹介だけで終わっていて、もやもやするのでこの記事を書きました。
自分の中ではパラドックスのありかがわかっているつもりなのですが、同意見の主張が見つからないので多少気になっているところでもあります。

ドロステ効果

Taken by fdecomite, Flickr


パラドックスの概要

抜き打ちテストのパラドックスというのは、以下のようなものです。

「とある学校、とあるクラスの話。あるとき先生が以下のように言いました。

『来週の月曜から金曜の間に、抜き打ちテストを行います。ただし、君たちはこの抜き打ちテストがいつ行われるか予測できない。』

続きを読む


最近のブログ記事まとめ


ざっくりとまとめておきます。

詳細は各記事へのリンクをどうぞ。


シミュレーション/ビジュアライゼーション系

[フラクタル] マンデルブロー集合 10の200乗倍への挑戦

コンピュータを駆使してグーゴル倍のさらにグーゴル倍まで拡大。なかなか恐ろしい計算でした。
浮動小数点型の限界なんて何のその。

運動方程式の数値計算と速度ベルレ法の威力 (前半)

ちょっと物理のお話。計算結果がずっと安定するという不思議な数値解法。

[作ってみた] [プログラミング] 剛体3重振り子

剛体系の動きをどうコンピュータの世界に落としこむか、という話。かわいい。

[作ってみた] [プログラミング] 反応拡散方程式で遊ぶ

偏微分方程式と戯れる。単純な式から複雑な模様を描く。ぬるぬる。


その他作ってみた系

男子トイレの力学

モンテカルロ法の授業の課題で作ったもの。

続きを読む