In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

麻雀の待ち問題を少し真面目に書き直した

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html

の問題を解いてみた
いろいろ面倒だったので深く考えずに正規表現でガンガン回す方針

回答を提出した半日後に少し真面目に書き直した
Get Adobe Flash player
by kaikoga 03 Apr 2010
    Embed
/**
 * Copyright kaikoga ( http://wonderfl.net/user/kaikoga )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/Ah4X
 */

// forked from kaikoga's 麻雀の待ち問題をやってみた
// forked from kaikoga's trace("自分用")
package {
    
    /*
     * makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ
     * http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html
     * 
     * の問題を解いてみた
     * いろいろ面倒だったので深く考えずに正規表現でガンガン回す方針
     * 
     * 回答を提出した半日後に少し真面目に書き直した
     */
    
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    public class FlashTest extends Sprite {
        
        private var v:Array = [];
        
        public function FlashTest() {
            this.machiOut("1112224588899"); //(111)(222)(888)(99)[45]
            this.machiOut("1122335556799"); //(123)(123)(555)(99)[67]、(123)(123)(55)(567)[99]、(123)(123)(99)(567)[55]
            this.machiOut("1112223335559"); //(123)(123)(123)(555)[9]と(111)(222)(333)(555)[9]
            this.machiOut("1223344888999"); //4をアタマにしての[23]待ちと、1単騎、4単騎で3個の答えになります。
            this.machiOut("1112345678999"); //九蓮宝燈
        }
        
        public function machiOut(input:String):void {
            this.trace("machi(" + input + "): ");
            this.trace(this.machi(input));
            this.trace();
        }

        public function machi(input:String):String {
            return this.doMachi(input).join(", ");
        }

        private function doMachi(input:String):Array {
            //Internal intermediate format: "14588899@(11)(222)"
            //Unorganized tiles and "@", followed by organized sets
            var intermediate:Array = [input + "@"];
            
            //Extract atama only once
            var intermediateNoAtama:Array = [];
            for each (var atama:String in ["11", "22", "33", "44", "55", "66", "77", "88", "99"]) {
                this.tryAddExtractSet(intermediate, atama, intermediateNoAtama, false);
            }
            
            //Extract sets many times
            for each (var koutsu:String in ["111", "222", "333", "444", "555", "666", "777", "888", "999"]) {
                this.tryAddExtractSet(intermediate, koutsu, null, true);
                this.tryAddExtractSet(intermediateNoAtama, koutsu, null, true);
            }
            for each (var shuntsu:String in ["123", "234", "345", "456", "567", "678", "789"]) {
                this.tryAddExtractSet(intermediate, shuntsu, null, true);
                this.tryAddExtractSet(intermediateNoAtama, shuntsu, null, true);
            }
            
            //intermediate = intermediate.concat(intermediateNoAtama);
            intermediate = this.filterTanki(intermediate).concat(this.filterPairMachi(intermediateNoAtama));
            var result:Array = [];
            for each (var hand:String in intermediate) {
                result.push(hand.split("@", 2)[1]);
            }
            return result.sort();
        }
        
        private function filterPairMachi(hands:Array):Array {
            //filters machi created with double tiles and extract
            var result:Array = [];
            for each (var hand:String in hands) {
                if (hand.indexOf("@") == 2) {
                    switch (hand.charCodeAt(1) - hand.charCodeAt(0)) {
                        case 2:
                        case 1:
                        case 0:
                        result.push(this.extractMachi(hand));
                        break;
                    }
                }
            }
            return result;
        }
        
        private function filterTanki(hands:Array):Array {
            //filters machi created with single tile and extract
            var result:Array = [];
            for each (var hand:String in hands) {
                if (hand.indexOf("@") == 1) {
                    result.push(this.extractMachi(hand));
                }
            }
            return result;
        }
        
        private function extractMachi(hand:String):String {
            //The machi must be valid, check is done in filter~ methods
            var handArray:Array = hand.split("@", 2);
            var sets:String = handArray[1];
            var machi:String = handArray[0];
            sets = (")" + sets + "(").split(")(").slice(1, -1).sort().join(")(");
            sets = "(" + sets + ")";
            return "@" + sets + "[" + machi + "]";
        }
        
        private function tryAddExtractSet(hands:Array, tiles:String, target:Array = null, multiple:Boolean = false):Boolean {
            //Add to array if tryExtractSet() succeeds with unique result
            //Does multiple application if (multiple == true)
            target ||= hands;
            var success:Boolean = false;
            var regExp:RegExp = new RegExp("(.*)" + tiles.split("").join("(.*)") + "(.*)@(.*)");
            //trace("Main.tryAddExtractSet(): RegExp: ", regExp.source);
            var c:int = hands.length;
            for (var i:int = 0; i < c; i++) {
                var hand:String = hands[i];
                var newHand:String = tryExtractSet(hand, tiles, regExp);
                if (newHand && hands.indexOf(newHand) < 0) {
                    target.push(newHand);
                    success = true;
                    if (multiple) {
                        c++;
                    }
                }
            }
            return success;
        }
        
        private function tryExtractSet(hand:String, tiles:String, regExp:RegExp):String {
            //Extracts set from unorganized section and append to organized section
            var tileCount:int = tiles.length;
            if (hand.indexOf("@") < tileCount) {
                return null;
            }
            var exec:Object = regExp.exec(hand);
            if (!exec) {
                return null;
            }
            var result:String = "";
            for (var i:int = 1; i <= tileCount + 1; i++) {
                result += exec[i];
            }
            result += "@" + exec[i] + "(" + tiles + ")";
            //trace("Main.tryExtractSet(): Extraction: ", hand, "->", tiles, "=>", result, "//", exec)
            return result;
        }
        
        
        private var _traceField:TextField;
        public function trace(...message):void {
            if (!this._traceField) {
                this._traceField = new TextField();
                this._traceField.width = this.stage.stageWidth;
                this._traceField.height = this.stage.stageHeight;
                this._traceField.defaultTextFormat = new TextFormat("_typewriter", 10);
                this._traceField.wordWrap = true;
                this.addChild(this._traceField);
            }
            this._traceField.appendText(message.join(" ") + "\n");
        }
        
    }
}