巻き込まれ人生

2009-09-22

[]喫茶店のはずが 16:52

薔薇無線LANの使える喫茶店でプログラミングをすることになった。

とりあえず京都市内の適当な店を見繕って突撃。


錦小路の近くにある店で行けるみたいでいってみた。


・・・喫茶店の系列のフランス料理屋だった!


しかもコースしか選択肢がねぇ!

まったりとコース料理食べてきましたよ。

ええ、ノートパソコンとか出せる空気じゃないのでおとなしくしてました。


というわけで、現在はロフトに入ってるシアトルコーヒー無線LAN使ってます。

最初からこうすればと言う話はなしの方向で。


そしてプログラミングをせずにたまったブログの記事を消化してた。

あれ?

なんか当初と目的がずれてきている気がするけど

・・・まあいいか。

[]FizzBuzzについて考えてみた 17:58

全てのことの発端はこのブログだと思う。

どうしてプログラマに・・・プログラムが書けないのか?


個人的にはプログラムの多くの処理は制御と条件分岐で成り立ってる思ってる。


FizzBuzzには制御(繰り返し処理)と条件分岐が必要となるため、

これができるかできないかでプログラム能力があるかないかがわかるわけだ。


逆に考えればこれができればプログラムの基礎的なことがわかっているとも言える。

じゃあこれを教材にすればいいのではないかと思った。

class FizzBuzz{

    private static void printFizzBuzzV1(){
        for(int i = 1; i <= 100; i++){
            if(i % 15 == 0){
                System.out.println("FizzBuzz");
            }else if(i % 3 == 0){
                System.out.println("Fizz");
            }else if(i % 5 == 0){
                System.out.println("Buzz");
            }else{
                System.out.println(i);
            }
        }
    }

    private static void printFizzBuzzV2(){
        for(int i = 1; i <= 100; i++){
            String ans = "";
            if(i % 3 == 0) ans += "Fizz";
            if(i % 5 == 0) ans += "Buzz";
            if(ans.equals("")) ans += i;
            System.out.println(ans);
        }
    }


    private static void printFizzBuzzV3(){
        for(int i = 1; i <= 100; i++)
            System.out.println(i%3<1?i%5<1?"FizzBuzz":"Fizz":i%5<1?"Buzz":i);
    }

    public static void main(String[] args){
        printFizzBuzzV1();
        printFizzBuzzV2();
        printFizzBuzzV3();
    }
}

FizzBuzzの問題文をそのまま実装するのならば多分V1のような実装になると思う。

    private static void printFizzBuzzV1(){
        for(int i = 1; i <= 100; i++){
            if(i % 15 == 0){
                System.out.println("FizzBuzz");
            }else if(i % 3 == 0){
                System.out.println("Fizz");
            }else if(i % 5 == 0){
                System.out.println("Buzz");
            }else{
                System.out.println(i);
            }
        }
    }

まずはじめに、1〜100の繰り返しの処理を行う必要がある。

ここでwhile文を使おうがfor文を使おうが個人の好みだと思うが普通はforを使うはず。

ちなみにforの使い方は以下の通りである。

for(初期処理; 終了条件判定; 末尾処理){
  //処理内容
}

今回の初期処理は1~100ということでint型の変数iに1を代入する。

次に終了条件は100までということで、

for(int i = 1; i <= 100; i++)

ここで気をつけるべき内容としては

× i < 100
○ i <= 100

上ではiが100より小さい(100未満)と言う判定のため、100自身が含まれない。

下はiが100以下という判定のため、100自身が含まれる。


プログラムを始めたばかりの頃は<を使うべきなのか<=を使うべきなのかの判断が難しい。

そのためバグが生じやすいのはだいたいこうした判定文まわりになる。

次に気にしたいのがプログラムの処理の順番。

ここで注意するべきは先に15で割り切れるかを判定すること。

多くのプログラミング言語は上から順に計算が行われる。


そのため、3や5で割り切れるかと言った判定分を先に書いてしまうと、

15で割り切れる数は先に3や5で割り切れるために15で割り切れるかの判定が行われないまま、

処理が行われる。


つまり、まずはプログラムがどのような順に実行されているかを意識していなければ、

ここでつまずくことになる。


しかし、V1はあまりにきれいなコードとは言えない。

というわけで、V2の用なコードを書いてみた。

    private static void printFizzBuzzV2(){
        for(int i = 1; i <= 100; i++){
            String ans = "";
            if(i % 3 == 0) ans += "Fizz";
            if(i % 5 == 0) ans += "Buzz";
            if(ans.equals("")) ans += i;
            System.out.println(ans);
        }
    }

繰り返しの処理に関してはV1と同じ。

処理が違っている部分としては以下の数点

  • String型の変数ansを使って出力する文字を決める
  • iが3で割り切れるときansに"Fizz"を追加
  • iが5で割り切れるときansに"Buzz"を追加
  • ansが空のときansに現在のカウントであるiを追加
  • 最後にansを出力する

これがベストかと問われるとよくわからないが、

少なくとも何も考えていないV1よりはスマートな解答だと思う。


FizzBuzzを通して問題を解くだけでなく、

問題の解き方をみることでその人のプログラミング能力のレベルもわかる気がする。

定期的にFizzBuzzのような問題を解いてみて、

自分がどういったレベルなのかを把握するのもありなのではないかと思う。


最後のおまけとしてShort Codingしておく。

    private static void printFizzBuzzV3(){
        for(int i = 1; i <= 100; i++)
            System.out.println(i%3<1?i%5<1?"FizzBuzz":"Fizz":i%5<1?"Buzz":i);
    }

どうしてこうなったかは自分で考えてみよう。

[][]RubyFizzBuzzしてみた 02:31

1.upto(?d){|i|i%3<1&&x=:Fizz;puts i%5<1?"#{x}Buzz":x||i}

ポイントは以下の通り

  • 「100」を「?d」と使用することで1文字短縮
  • 三項演算子を利用
  • &&の「左辺の処理が真なら右辺の処理を行う」を活用
  • Rubyは式ごとに値を返すので&&の右辺が実行された場合は値が返るため真である
  • :FizzとSymbolを使うことでStringの"Fizz"と比べ1文字短縮
  • "#{x}Buzz"と文字内部に式を利用
  • 初期化されていない変数nilである
  • nil値は値を返さないためx=nilのとき"#{x}Buzz" => "Buzz"
  • Rubyの条件判定はnilの時もfalseとされる
  • 「x||i」はxがnilでない場合xが評価される、xがnilの場合はiが評価される

pascal256pascal256 2009/09/26 18:41 毎回printするのがいけてないような。ちゃんと一度は文字列に出力しようよ

トラックバック - http://d.hatena.ne.jp/Mazin/20090922