Perlによるテキスト思考アプローチでFizzBuzz問題を解く

NHK『とと姉ちゃん』の高畑充希、ドコモのコマーシャルにも出てたんですねえ。全然気づきませんでした。
CM内の斎藤さんゲームがずっと気になってました。朝いつもよりも遅い時間に家を出たら、登校中の小学生の列の中に、斎藤さんゲームやってる軍団発見。ああ小学生にとっては日常のゲームなんだと初めて知りました。ルールはわかりませんでしたが、一般普及している遊びということが判っただけで胸がいっぱいで、要するに世界のナベアツだろう、3の倍数だろう、と自己完結しました。

Eric S. Raymond氏がHow To Become A Hacker
で、学ぶべきプログラミング言語として、Python、Java、C/C++、Perl、LISPをあげており(当時がこれらの言語だったか、この順序だったかは記憶にないのですが)、プログラミング初心者だったころの私が、最初に覚えたのがC/C++でした。
その次にPerl、Javaといった順序で手をつけ始めました。プログラミング言語の学習をC言語から入ると、どうしてもC思考になってしまいます。始めた順序がPerlは2番手だったのにも関わらず、Perlとしてのプログラングは身につかず、結局修得はJavaの方が早かった気がします。
(Javaがオブジェクト指向であり、オブジェクト指向というものが人間向けとして一番とっつきやすいかったのもあります)
Perlの修得が遅かった原因としては、書店で売られているPerl関連の書籍が、ほとんどCGI向けの入門書だったからでしょう。Perlでなくてもいいサンプルプログラムを見ながらC言語思考のままPerlを使えるようになっても、それはC言語の延長でしかなかったのです。

Fizz-Buzz問題

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

1から100までの数を表示するプログラムを書け。ただし、3の倍数は数の代わりに”Fizz”、5の倍数なら”Buzz”と表示し、3と5両方の倍数なら”FizzBuzz”と表示しろ。

C言語とかならこんな風なんでしょうけど

int main()
{
	int i,flag=0;
	for(i=1; i<=100; i++){
		flag = 0;
		if(0==i%3){
			printf("Fizz");
			flag = 1;
		}
		if(0==i%5){
			flag = 1;
			printf("Buzz");
		}
		if(flag == 0)	
			printf("%d\n",i);
		else
			printf("\n");
	}
	return 0;
}

Perlを知らない頃の私のプログラムは、というと、

for($i=1; $i<=100; $i++){
	$flag = 0;
	if(0==$i%3){
		printf("Fizz");
		$flag = 1;
	}
	if(0==$i%5){
		$flag = 1;
		printf("Buzz");
	}
	if($flag == 0){
		printf("%d\n",$i);
	}else{
		printf("\n");
	}
}

はい、そうです。全然Perlじゃないですね。
でも、どうにでも書ける、というのもPerlの良さです。

Perlのことが分かってきた時、 「悟り」みたいなものも感じたかもしれません。複数の言語を学ぶと、こんな素晴らしい体験ができるのか、モノクロだった世界に色がついたよ、星たちも輝き出すよ、空だって飛べるよ、ぐらい感動しました。
「悟り」なので、何がどうすごく感じたのかは人に説明するのはとても難しいのですが、とにかくプログラミングの面白さに拍車をかけました。
そしてPerlのことをテキスト思考言語と勝手に呼び始めました。

FizzBuzzですが、Perlではこんな風にも書けます。

foreach (1 .. 100){
        $n = $_; 
        s/\d*/Buzz/ unless $n % 5;
        s/\d*/Fizz/ unless $n % 3;
        print"$_\n";
}

FizzBuzzの解答としては、合格にはならないかもしれませんが、私はこちらの方が好きですね。

まあ、ここまでPerlを絶賛しておいてなんですが、コマンドラインは当然一行です。sedを使いましょうか。

seq 100 | sed '0~3s/[0-9]*$/Fizz/;0~5s/[0-9]*$/Buzz/' | pr -t5
1             Fizz          41            61            Fizz
2             22            Fizz          62            82
Fizz          23            43            Fizz          83
4             Fizz          44            64            Fizz
Buzz          Buzz          FizzBuzz      Buzz          Buzz
Fizz          26            46            Fizz          86
7             Fizz          47            67            Fizz
8             28            Fizz          68            88
Fizz          29            49            Fizz          89
Buzz          FizzBuzz      Buzz          Buzz          FizzBuzz
11            31            Fizz          71            91
Fizz          32            52            Fizz          92
13            Fizz          53            73            Fizz
14            34            Fizz          74            94
FizzBuzz      Buzz          Buzz          FizzBuzz      Buzz
16            Fizz          56            76            Fizz
17            37            Fizz          77            97
Fizz          38            58            Fizz          98
19            Fizz          59            79            Fizz
Buzz          Buzz          FizzBuzz      Buzz          Buzz

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA