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.

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

Posted at

http://nabetani.sakura.ne.jp/hena/ord17foldcut/
http://qiita.com/Nabetani/items/ebd9d7deb30c57447806

折って切る、何処かで見たと思ったら第18回の参考問題に似ている。
なので同じように考えれば解けるかな?

<?php

	class FOLDCUT{
	
		/**
		* 折って切る
		* @param String 「RRTRB-bl」みたいな文字列
		* @return int 「6」みたいな数値
		*/
		public function get($input){
			// 入力値を分解
			$input = explode('-', $input);
			$loop = str_split(strrev($input[0]), 1);
			
			// 初期値を作成
			switch($input[1]){
				case 'tl': $data = ['01', '11']; break;
				case 'tr': $data = ['10', '11']; break;
				case 'bl': $data = ['11', '01']; break;
				case 'br': $data = ['11', '10']; break;
			}
			
			// 展開する
			foreach($loop as $key=>$val){
				$data = $this->{'extract'.$val}($data);
			}
			
			// 穴を数えて返す
			$count = $rowflg = $colflg = 0;
			$collen = strlen($data[0]);
			foreach($data as $row=>$line){
				// 穴は必ず2*2になるので、右上でカウントしたら下の行は飛ばす
				if($rowflg){ $rowflg=0;continue; }
				$colflg = 0;
				for($col=0;$col<$collen;$col++){
					// 空があった
					if(!$line[$col]){
						// 最上段/最下段は穴にならない
						if(!$row || !isset($data[$row+1])){
							$rowflg++;
							continue;
						}
						// 次が1であればカウント
						if($colflg && isset($line[$col+1]) && $line[$col+1]){
							$count++;
							$rowflg++;
							continue;
						}
					// 空がなかった
					}else{
						$colflg++;
					}
				}
			}
			return $count;
		}
		
		// 右半分を手前に折って、左半分に重ねる
		private function extractR($data){
			return array_map(function($val){
				return $val . strrev($val);
			}, $data);
		}
		
		// 左半分を手前に折って、右半分に重ねる
		private function extractL($data){
			return array_map(function($val){
				return strrev($val) . $val;
			}, $data);
		}
		
		// 上半分を手前に折って、下半分に重ねる
		private function extractT($data){
			return array_merge(array_reverse($data), $data);
		}
		
		// 下半分を手前に折って、上半分に重ねる
		private function extractB($data){
			return array_merge($data, array_reverse($data));
		}
		
	}
	
	// 以下はテスト
	$test = [
		['RRTRB-bl', '6'],
		['R-tr', '0'],
		['L-br', '0'],
		['T-tl', '0'],
		['B-tl', '0'],
		['BL-br', '0'],
		['LB-tl', '0'],
		['RL-tl', '0'],
		['BL-tl', '0'],
		['TL-bl', '0'],
		['RT-tr', '1'],
		['TRB-tl', '0'],
		['TRL-bl', '0'],
		['TRB-br', '2'],
		['LLB-bl', '2'],
		['RTL-tr', '1'],
		['LBB-tr', '0'],
		['TLL-tl', '2'],
		['RLRR-tr', '0'],
		['BBTL-tl', '4'],
		['TBBT-tr', '0'],
		['LLBR-tl', '0'],
		['LBRT-tl', '2'],
		['RLBL-bl', '4'],
		['BRRL-br', '3'],
		['TBBTL-tl', '8'],
		['TLBBT-br', '0'],
		['LRBLL-br', '7'],
		['TRRTT-br', '6'],
		['BBBLB-br', '0'],
		['RTTTR-tl', '4'],
		['BBLLL-br', '6'],
		['RRLLTR-tr', '16'],
		['TTRBLB-br', '8'],
		['LRBRBR-bl', '14'],
		['RBBLRL-tl', '8'],
		['RTRLTB-tl', '12'],
		['LBLRTR-tl', '14'],
		['RRLTRL-tl', '16'],
		['TBLTRR-br', '12'],
		['TTTRLTT-bl', '30'],
		['TBBRTBL-tr', '15'],
		['TRTRTLL-tr', '28'],
		['TLLRTRB-tr', '24'],
		['RLLBRLB-tr', '15'],
		['LTLRRBT-tr', '32'],
		['RBBRBLT-br', '21'],
		['LLRLRLR-tr', '0'],
	];

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

解けませんでした。
展開図を作るところまでは同じなので一瞬だったのですが、そこから穴の数をどうやって数えるのかというところで詰まった。
結局今回の展開図の特徴を用いた超力業で解きました。
かかった時間は1.5時間くらい。

絶対なんかもっとまともな数え方があるはず。
というか図にせずに計算する方法があるはず。

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?