LoginSignup
5
5

More than 5 years have passed since last update.

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

Posted at

http://qiita.com/Nabetani/items/1c83005a854d2c6cbb69
http://nabetani.sakura.ne.jp/hena/ord24eliseq/
多段階選抜

PHPには無限リストとか無いので、とりあえず大きな配列を作っておいて順に消していくという方針にするしかなさそうです。
イテレータやジェネレータを使うのも、このややこしい選抜条件では難しそうです。
うまく使える方法があれば誰か教えてください。

<?php
    class ELISEQ{

        /**
        * 多段階選抜
        * @param String 「ss6cc24S」みたいな文字列
        * @return String 「1,9,21,30,33,37,42,44,49,56」みたいな文字列
        */
        public function get($input){
            // 1スタートの配列
            $this->list = range(0, 1100);
            unset($this->list[0]);

            // 各文字でくるくる
            $length = strlen($input);
            for($i=0;$i<$length;$i++){
                // 適切なメソッドを実行
                if((string)(int)$input[$i] === $input[$i] ){
                    $this->_removeI((int)$input[$i]);
                }elseif($input[$i] === 'h'){
                    $this->_removeH();
                }elseif(strtolower($input[$i]) === $input[$i]){
                    $this->{'_removeB'.$input[$i]}();
                }else{
                    $this->{'_removeA'.$input[$i]}();
                }
            }

            return implode(',', array_slice($this->list, 0, 10));
        }

        /**
        * 引数の倍数番目の値を削除。1スタート
        * @param int 2-9
        */
        private function _removeI($int){
            $i=1;
            foreach($this->list as $val){
                if($i++===$int){
                    unset($this->list[$val]);
                    $i=1;
                }
            }
        }
        /**
        * 累乗数の次を削除
        * @param int n乗根
        */
        private function _removeAS($n = 2){
            $delFlg = false;
            foreach($this->list as $val){
                if($delFlg){
                    unset($this->list[$val]);
                    $delFlg = false;
                }
                if(gmp_intval(gmp_rootrem($val, $n)[1]) === 0){
                    $delFlg = true;
                }
            }
        }
        /**
        * 累乗数の前を削除
        * @param int n乗根
        */
        private function _removeBs($n = 2){
            $before = reset($this->list);
            foreach($this->list as $val){
                if(gmp_intval(gmp_rootrem($val, $n)[1]) === 0 && $val !==1 ){
                    unset($this->list[$before]);
                }
                $before = $val;
            }
        }
        /**
        * 立法数の次を削除
        */
        private function _removeAC(){
            $this->_removeAS(3);
        }
        /**
        * 立法数の前を削除
        */
        private function _removeBc(){
            $this->_removeBs(3);
        }
        /**
        * 先頭100件を削除
        */
        private function _removeH(){
            $this->list = array_slice($this->list, 100, NULL, true);
        }

    }

    // 以下はテスト
    $test = [
        ['ss6cc24S', '1,9,21,30,33,37,42,44,49,56'],
        ['h', '101,102,103,104,105,106,107,108,109,110'],
        ['hh', '201,202,203,204,205,206,207,208,209,210'],
        ['hhh', '301,302,303,304,305,306,307,308,309,310'],
        ['2', '1,3,5,7,9,11,13,15,17,19'],
        ['22', '1,5,9,13,17,21,25,29,33,37'],
        ['222', '1,9,17,25,33,41,49,57,65,73'],
        ['3', '1,2,4,5,7,8,10,11,13,14'],
        ['33', '1,2,5,7,10,11,14,16,19,20'],
        ['333', '1,2,7,10,14,16,20,23,28,29'],
        ['s', '1,2,4,5,6,7,9,10,11,12'],
        ['ss', '1,4,5,6,9,10,11,12,13,16'],
        ['sss', '4,5,9,10,11,12,16,17,18,19'],
        ['S', '1,3,4,6,7,8,9,11,12,13'],
        ['SS', '1,4,7,8,9,12,13,14,15,16'],
        ['SSS', '1,8,9,13,14,15,16,20,21,22'],
        ['c', '1,2,3,4,5,6,8,9,10,11'],
        ['cc', '1,2,3,4,5,8,9,10,11,12'],
        ['ccc', '1,2,3,4,8,9,10,11,12,13'],
        ['C', '1,3,4,5,6,7,8,10,11,12'],
        ['CC', '1,4,5,6,7,8,11,12,13,14'],
        ['CCC', '1,5,6,7,8,12,13,14,15,16'],
        ['23', '1,3,7,9,13,15,19,21,25,27'],
        ['32', '1,4,7,10,13,16,19,22,25,28'],
        ['2h', '201,203,205,207,209,211,213,215,217,219'],
        ['h2', '101,103,105,107,109,111,113,115,117,119'],
        ['sC', '1,4,5,6,7,9,10,11,12,13'],
        ['Cs', '1,4,5,6,7,8,10,11,12,13'],
        ['s468', '1,2,4,6,7,11,12,16,17,20'],
        ['S468', '1,3,4,7,8,12,13,16,18,21'],
        ['cc579', '1,2,3,4,8,9,11,13,15,16'],
        ['CC579', '1,4,5,6,8,11,13,15,17,18'],
        ['85', '1,2,3,4,6,7,9,10,12,13'],
        ['sh', '110,111,112,113,114,115,116,117,118,119'],
        ['94h', '150,151,154,155,156,158,159,160,163,164'],
        ['h9c8', '101,102,103,104,105,106,107,110,111,112'],
        ['Cc3s', '1,3,5,6,10,11,13,16,17,19'],
        ['cs4h6', '149,150,152,153,154,157,158,160,161,162'],
        ['84523c', '1,3,11,15,23,26,34,38,46,49'],
        ['54C78hS', '228,231,232,233,236,241,242,243,246,247'],
        ['65h7ccs', '151,152,153,154,157,158,160,163,164,165'],
        ['c95hSc2C', '145,147,151,153,156,159,162,164,168,171'],
        ['c5h3Ss794', '130,131,133,137,138,142,148,150,152,157'],
        ['7ShscC846', '129,130,131,134,135,139,141,142,146,148'],
        ['cshSCCS7ch', '253,254,256,259,260,261,263,264,265,266'],
        ['hhC7849Ss6C', '201,202,203,205,206,211,212,216,220,225'],
        ['hhsc3C987Ccs', '201,202,204,205,207,208,214,217,218,220'],
        ['SC7S8hc59ss2', '162,169,174,178,182,185,188,194,199,203'],
        ['s7S6c35C9CShc', '367,371,377,379,380,385,387,388,392,395'],
        ['4scC3hh982Cc5s', '422,426,430,434,447,451,459,463,471,479'],
        ['23h465Ssc9CchC', '1027,1033,1045,1047,1057,1069,1071,1075,1081,1093'],
    ];

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

かかった時間はたぶん2時間くらい。

PHPはfunction hoge()function HOGE()が区別されないのでメソッド呼び出しが残念な感じに。

foreachで回しつつ、ひとつ手前や次を取り出す綺麗な手段がいまいち無いんですよね。
前回の値を持っておくというなんだかな方法に。

5
5
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
5
5