Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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

rana_kualu
不労所得で生きたい。
https://twitter.com/rana_kualu
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away