0 Comments
 こんにちは。すっかり波に乗り遅れた感がある逆FizzBuzzに挑戦してみました。私が読んだネタ元はこちらです。

逆FizzBuzz問題 (Inverse FizzBuzz)

 おもしろそうだったので自分も挑戦してみました。まあ挑戦と言ってもいつも通り Perl による力技なんですけどね。それではさっそくいってみましょう。

 ぱっと問題文を読んだ限り探索するのは100までとかなり狭い範囲なのでここはシンプルに探索用のテーブルを作ってしまうのがわかりやすいです。レインボーアタックならぬモノクロアタック。

 まずはFizzをF、BuzzをB、FizzBuzzをC、そのいずれでも無い数字は0として1〜100までのFizzBuzzの結果をずらずら連結します。結果は当然100byteの文字列となります。

00F0BF00FB0F00C00F0BF00FB0F00C
00F0BF00FB0F00C00F0BF00FB0F00C
00F0BF00FB0F00C00F0BF00FB0F00C
00F0BF00FB

 次に与えられたFizzBuzzの文字列を検索パターンに置換します。各 F/B/C の間には0個以上の「0」が入りますので仮に与えられた文字が「Fizz Buzz」だとするとこれを「F0*B」という正規表現にするわけです。

 つぎに生成した正規表現で検索テーブルにマッチングをかけます。とうぜん複数マッチすることもありますのでその場合は「マッチした文字列が最短のもの=もっとも解を返す数値の範囲がせまい」パターンを解答とします。

 数字の範囲ですが検索テーブル内でのbyte位置がそのまま数字の範囲になっているのでバイトを数えて(1byte文字なので単純に文字を数える)範囲を特定します。

 以下がソースです。

ソースのダウンロード

#!/usr/bin/perl
use strict;
use utf8;

binmode STDOUT, ":utf8";  #-画面に出力したい文字コード
binmode STDERR, ":utf8";  #-エラー出力に使いたい文字コード
binmode STDIN, ":utf8";  #-標準入力から入ってくる文字コード

# 検索用のテーブルを生成
# Fizz=F  Buzz = B FizzBuzz=C 数字=0
my $DB;
my $result;
my $Max = 100;
for (1..$Max) {
	$result = '';
	$result .= 'F' if ($_ %  3 == 0);
	$result .= 'B' if ($_ %  5 == 0);
	$result =~ s/FB/C/;
	$result = '0' if (0 == length($result));
	$DB .= $result;
}

sub GetFizzBuzz {
	#マッチパターンの生成
	my $key = '';
	my @FBC = @_;
	for (@FBC) {
		$_ =~ s/Fizz/F/i;
		$_ =~ s/Buzz/B/i;
		$_ =~ s/FB/C/;
	}
	$key =  join("0*",@FBC);

	# 範囲を特定する
	my $myStart = 0;
	my $myEnd = 0;
	my %Ans;
	if ($DB =~ /$key/g) {
		$Ans{'length'} = length($&);
		$Ans{'position'} = pos($DB);
		while ($DB =~ /$key/g) {
			if ($Ans{'length'} > length($&)) {
				$Ans{'length'} = length($&);
				$Ans{'position'} = pos($DB);
			}
		}
		$myEnd = $Ans{'position'};
		$myStart = $myEnd - $Ans{'length'} + 1;
		return join(" ",@_ , ':' , ($myStart .. $myEnd));
	} else {
		return 'Error';
	}
}

print GetFizzBuzz("fizz") . "\n";
print GetFizzBuzz("buzz") . "\n";
print GetFizzBuzz("fizz","fizz","buzz") . "\n";
print GetFizzBuzz("fizz","buzz") . "\n";
print GetFizzBuzz("buzz","fizz") . "\n";
print GetFizzBuzz("fizz","buzz","fizz") . "\n";
print GetFizzBuzz("fizz","fizz") . "\n";

exit;


結果:
fizz : 3
buzz : 5
fizz fizz buzz : 6 7 8 9 10
fizz buzz : 9 10
buzz fizz : 5 6
fizz buzz fizz : 3 4 5 6
fizz fizz : 6 7 8 9


ひらくん
Posted byひらくん

Comments 0

There are no comments yet.

Leave a reply