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()とかの使いどころを探してみたがちょっと無理だった。