1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「第8回オフラインリアルタイムどう書くの問題」をPHPで解く

Last updated at Posted at 2013-07-19

http://qiita.com/Nabetani/items/709d61dff282cff7a890
http://nabetani.sakura.ne.jp/hena/ord8biboma/

ボンバーマンで爆風が到達する場所を図示せよというお題。

解ける人はたぶんビット演算とかでずばしゃー!と解くのでしょうけど、私はそのあたりがよくわからないんですよね。
なので懇切丁寧に、2次元表になおすという人間に優しい解き方をしてみようと思います。

<?php

	class BOMBERMAN{
	
		/**
		* 爆風の範囲を返す
		* @param  String 「802b1200/01400c20」みたいな文字列
		* @return String 「53c40cfc」みたいな文字列
		*/
		public function get($input){
			
			// 入力値を2次元表に分解
			$array = explode('/', $input);
			$wall = str_split(substr(str_pad(base_convert($array[0], 16, 2), 32, '0', STR_PAD_LEFT), 0, -2), 6);
			$bomb = str_split(substr(str_pad(base_convert($array[1], 16, 2), 32, '0', STR_PAD_LEFT), 0, -2), 6);
			
			// 爆風の位置
			$blast = $bomb;
			
			// 爆弾の行でくるくる
			foreach($bomb as $key=>$val){
				// 爆弾の列でくるくる
				for($i=0; $i<strlen($val); $i++){
					// 爆弾があれば爆発
					if($val[$i] === '1'){
						$this->explosion($blast, $wall, $key, $i);
					}
				}
			}
			
			// 16進数に戻す
			return str_pad(base_convert(implode('', $blast) . '00', 2, 16), 8, '0', STR_PAD_LEFT);
		}
		
		/**
		* ば く は つ するーーー!
		* @param &array 爆風が通った場所が1になる
		* @param array 壁
		* @param int 列
		* @param int 行
		*/
		private function explosion(&$blast, $wall, $column, $row){
			// 行を1埋め
			$key1 = $key2 = $row;
			// 右に
			while(@$wall[$column][$key1] === '0'){
				$blast[$column][$key1++] = '1';
			}
			while(@$wall[$column][$key2] === '0'){
				$blast[$column][$key2--] = '1';
			}
			// 列を1埋め
			$key1 = $key2 = $column;
			while(@$wall[$key1][$row] === '0'){
				$blast[$key1++][$row] = '1';
			}
			while(@$wall[$key2][$row] === '0'){
				$blast[$key2--][$row] = '1';
			}
		}
		
	}
	
	// テスト
	$test = [
		['802b1200/01400c20', '53c40cfc'],
		/* 省略 */
	];

	$bomberman = new BOMBERMAN();
	foreach($test as $key=>$data){
		$answer = $bomberman->get($data[0]);
		if($answer !== $data[1]){
			print('えらー');
		}
	}

爆弾と壁と爆風の表も別々にする必要がなく、値を1,2,4とかにすれば1枚で済むのですが、面倒なのでわかりやすくするために別にしています。
実際計算中の値は以下のようになっており、

$wall = array(5) {
  [0]=>  string(6) "100000"
  [1]=>  string(6) "000010"
  [2]=>  string(6) "101100"
  [3]=>  string(6) "010010"
  [4]=>  string(6) "000000"
}
$bomb = array(5) {
  [0]=>  string(6) "000000"
  [1]=>  string(6) "010100"
  [2]=>  string(6) "000000"
  [3]=>  string(6) "001100"
  [4]=>  string(6) "001000"
}
$blast = array(5) {
  [0]=>  string(6) "010100"
  [1]=>  string(6) "111100"
  [2]=>  string(6) "010000"
  [3]=>  string(6) "001100"
  [4]=>  string(6) "111111"
}

実に人間に優しい形で確認することができます。
かかった時間は3時間くらい。
ビット演算はわかんないとか言いつつ実際やってみようと延々挑戦したあげく挫折したとかいう歴史があったりなかったり。

なおgmp_scan1()とかの使いどころを探してみたがちょっと無理だった。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?