« 猫のゆりかご/カート・ヴォネガット | Main | "文学少女"と飢え渇く幽霊/野村美月 »

FizzBuzz問題

遅ればせながら。というか、まあ、特に参加する気もなかったんですが。

(FizzBuzz問題については「どうしてプログラマに・・・プログラムが書けないのか?」を参照してください)

ずいぶんと前にRubyの本を紹介したYukaさんから、「面白そうだからやってみる。添削して」と送られてきました。さすがに、そういうことだと先に自分の回答を用意しとかないとだめですよね。というわけで、ちょちょいと。実際に割り算をするのはつまらない。ルールに従った文字列が出ればいいということで、こんな感じでコーディングしました。

f = ["","","Fizz"] * 34
b = ["","","","","Buzz"] * 20

Array.new(100){|i| f[i] + b[i] == "" ? (i+1).to_s : f[i] + b[i] }.each{|i| puts i}

nacに見せたら「富豪だね」とのことでした。

ちなみに勝手に載せちゃうけどYukaさんのは、こう

i = 1

while i <= 100
  amari_3 = i.modulo(3)
  amari_5 = i.modulo(5)

  if amari_3 == 0 && amari_5 == 0
    print("FizzBuzz \n")
  elsif amari_3 == 0
    print("Fizz \n")
  elsif amari_5 == 0
    print("Buzz \n")
  else
    print(i, "\n")
  end

  i = i + 1
end

過不足なく、非常に素直。人柄が偲ばれます。Rubyっぽくはないけど、かえって汎用的でよく見えますね。

さすがにRubyなら2分で書けるわけですが、これをCで・・・と言われると、ちょっと時間がかかりますなあ。20分ぐらいかけて、えいやっ

#include <stdio.h>

int main(int argc, char **argv){
    char f[] = "Fizz";
    char b[] = "Bazz";
    char n[] = "";
   
    char **p3,**p5;
   
    int i;
   
    char *factor_3[] = {n,n,f,NULL};
    char *factor_5[] = {n,n,n,n,b,NULL};
   
    p3 = factor_3;
    p5 = factor_5;
   
    for(i = 0; i < 100; i++){
        if(*p3 == NULL){
            p3 = factor_3;
        }
       
        if(*p5 == NULL){
            p5 = factor_5;
        }
       
        printf("%s%s",*p3,*p5);
        if(*p3 == n && *p5 == n){
            printf("%d",i+1);
        }
        printf("\n");
        p3++;
        p5++;
    }
}

いや、割り算使えばもう少し早いよ、多分(笑)

|

« 猫のゆりかご/カート・ヴォネガット | Main | "文学少女"と飢え渇く幽霊/野村美月 »

パソコン・インターネット」カテゴリの記事

Comments

んー、ちょっとCのプログラムがひどいんでないかい?
ひどいのは、
1.空文字列なのをいいことに常にprintfしていること
2.Cだって3項演算子くらいあるのにそれをつかっていないこと
3.nをアドレスで判断するってのはどうよ?

まずCで富豪したいならmallocは当然でしょう。
そっから元ネタ(Ruby)と同じようにきちんと配列を作ってあげてもそんなに行数は食わない。
むしろNULL判定の部分が減って全体に短くなるでしょう。
アロケート時に初期化できる関数もあったはずだから\0で埋めといて**p='\0'で判断すれば逆にfizzとbuzzを埋める作業が定数でスキップできるはず。そうするとRubyの元配列を繰り返すよりも効率が良いかもしれません。

しかし最大の問題はうちの社員の何人がこれを書けるか?だよなぁ。
後、nacさんによろしく伝えてください。Haskellの約束守ってなくてすみません。JavaFXScriptもHaskell的な要素があって面白いそうですよ。
んでは。

Posted by: こ | May 21, 2007 12:50 PM

なんでこんな発想になっているかというと、そもそもRuby版で、「34倍ってモロに数字が入ってるのがダサイ」っていうのがあったわけですよ。無限配列が欲しいね。Haskellいいねと(笑)

でも、リンクリスト作ってとかいうのもアレだし、Arrayにメソッド追加するのも大袈裟だし、Cだったら番兵立てて終わりなのにね・・・というのが、そもそもC版をつくった時の発想なわけ。だから、

> nをアドレスで判断するってのはどうよ?

ってのは、コンセプトに関わる問題ですな。ポインタの配列を走査してるんだから、アドレスがNULLを指してるものを拾うのは自然な発想だと思うけど。そのポインタが指してる先の値をみて決めるなんて、素直じゃなくないかい?

それに、mallocした領域に配列をN回コピーなんてソース、コワイから書かないよ。絶対バグる自信があります(笑)

> 逆にfizzとbuzzを埋める作業が定数でスキップできるはず

ここは疑問です。どうやるんだろう?埋める作業がそのまま答えを出力するコードになっちゃわない?それじゃ意味がないぞ?

しかし、そんなにひどいかなあ?あげられたポイントがピンと来ないな

> しかし最大の問題はうちの社員の何人がこれを書けるか?だよなぁ。

どうだかねえ。ま、自分が仕事で使う言語で書ければいいわけですよね。そりゃ、Cでコード書ける人は1000人に一人ぐらいかもしれないけど、それはそれでもいいよね(笑)。自分の得意な言語、あるいは、今仕事で使ってる言語で・・・っていうことになるとどうだろう。書けないのはやっぱりSEでも問題だろうなあ。書けない人、いるだろうね。困ったもんだね。

私もJavaでは書けないけど、いいのだ。Java使わないから。使ってる言語なら書けるぞ。Kshでもばっちりだ。Antで・・・えーっと・・・どうだろう???(笑)

あと、この場合、3項演算子はよくないと思う。

Posted by: Tambourine | May 21, 2007 09:08 PM

うす。

>Cだったら番兵立てて終わりなのにね

なるほど。だけど解としてはRubyのほうが美しいと思うよ。NULL判定増えているし。
どちらかというとif文が減ったほうがバグは減るでしょ?

>そのポインタが指してる先の値をみて決めるなんて、素直じゃなくないかい?

どうかな?

char*の配列だから仮に(char*)0を埋めた時に判定するのは*p==0でアドレス判定になる。
ここは私の間違い。
ただこれを書いたときにはchar*では"fizz","buzz",""の3つ以外も代入できるし、プログラム的に後から読んで意味がわかりやすいのはアドレスがnであるかよりも対象が空文字列であるか、だと思った。

今思ったのだが、これをやるならやはりenumでやりたい。テーブルはenumしか取らないようにして、enumは値指定で0,1,2

char* val[] = {"", "fizz","buzz"}

の引数を取る。これだとテーブルはbyteの配列で済む。富豪じゃなくなってしまうが(w

>mallocした領域に配列をN回コピー

そうじゃないでしょ?
callocで必要な領域を0で取り、3の倍数、5の倍数を埋めていくわけだ。
また逆に配列をコピーする場合でもC言語ではsizeof関数があるから絶対に間違わない。
普通にmemcpyを繰り返すだけですわ。

>埋める作業がそのまま答えを出力するコード

いや、元のRubyと同じになるだけだけどね。
元々問題が禁止していないので正解の配列を作るのもありだけど。
Schemeの人やbashの人はやはり1から100の配列を作って交換していたな。
ワンライナーやらMS-DOSのバイナリとか随分と流行っているね。(笑

>しかし、そんなにひどいかなあ?

無駄なコードが多いの一言。
Rubyだと綺麗なのになんでCだと無駄が気にならんかね?
富豪にした上で余計なコード書くなら素直にfor文1から100まで回したほうが良くない?
20分かかっているのはデータ構造が悪い分、余計なコードが増えているからだよ。

>この場合、3項演算子はよくないと思う。

なんでよ?
Rubyでは使っているのに?

ならせめて、
printf("%s%s",*p3,*p5);
if(*p3 == n && *p5 == n){
printf("%d",i+1);
}
は、if-elseでしょう?
これは起動を抑えないと将来の変更でバグるよ。

>書けない人、いるだろうね。

書くことを教えないことが一番の問題だと思うのだけどね。

Posted by: こ | May 22, 2007 01:31 AM

Post a comment



(Not displayed with comment.)


Comments are moderated, and will not appear on this weblog until the author has approved them.



TrackBack


Listed below are links to weblogs that reference FizzBuzz問題:

« 猫のゆりかご/カート・ヴォネガット | Main | "文学少女"と飢え渇く幽霊/野村美月 »