忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2024/11/23 16:30 |
PHP5.3.7 「第8回オフラインリアルタイムどう書くの問題」をPHPで解く
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;
			// 爆弾より右が壁にぶつかるまで1で埋める。以下同じ
			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()とかの使いどころを探してみたがちょっと無理だった。


「オフラインリアルタイムどう書く」の一覧
PR


2013/07/19 23:59 | Comments(0) | PHP

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<今週の実績 2013/07/21 | HOME | PHP5.3.7 「第9回オフラインリアルタイムどう書くの参考問題」をPHPで解く>>
忍者ブログ[PR]