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


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時間くらい。

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