Project Euler 154 (unsolved)

by uwi
@see http://projecteuler.net/index.php?section=problems&id=
unsolvedというよりは時間がかかりすぎて答えがでない。
Javaに移植したら正答を出したので、時間のかかる再帰を展開して
frameごとに実行すればいけるはず
♥0 | Line 153 | Modified 2010-04-18 23:50:29 | MIT License
play

ActionScript3 source code

/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mDhZ
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    import flash.events.Event;
    import com.bit101.components.*;
    
    // @see http://projecteuler.net/index.php?section=problems&id=
    [SWF(frameRate=1)]
    // unsolvedというよりは時間がかかりすぎて答えがでない。
    // Javaに移植したら正答を出したので、時間のかかる再帰を展開して
    // frameごとに実行すればいけるはず
    public class Euler extends Sprite {
        private var _tf : TextField;
  
        public function Euler() {
            _tf = new TextField();
            _tf.width = 465;
            _tf.height = 465;
            addChild(_tf);
            
            var s : int = getTimer();
            
//            tr(solve2(3, 100));
//            tr(solve(3, 100)); 
            solve(14, 200000);
            var g : int = getTimer();
            tr((g - s) + " ms");
             
            var pb : PushButton = new PushButton(this, 350, 10, "stop", function(e : Event) : void
                {
                    removeEventListener(Event.ENTER_FRAME, onEnterFrame);
                });
            pb.width = 100;
        }

        private var _t5 : Vector.<Array>;
        private var _N : uint;
        private var _M : uint;

        private function solve(M : uint, N : uint) : void
        {
        		_N = N;
        		_M = M;
             var i : int, j : int, k : int;
            _t5 = new Vector.<Array>(15);
            for(i = 0;i < 15;i++)_t5[i] = [];
            for(i = 0;i < 5;i++){
                for(j = 0;j < 5;j++){
                    for(k = 0;k < 5;k++){
                        _t5[i + j + k].push([i, j, k]);
                    }
                }
            }
            
            _C2 = [];
            for(i = 0;i <= _N;i++){
            		var sum : uint = 0;
	            for(j = i >>> 1;j > 0;j >>>= 1)sum += j;
	            _C2.push(sum);
            }
            
            _ptns = srec(N, 0, [], N);
//            tr(_ptns.join('\n'));
//            tr(_ptns.length);
            _p = 0;
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        private var _C2 : Array;
        
        private function onEnterFrame(e : Event) : void
        {
            var s : int = getTimer();
            
            _ar = _ptns[_p];
            var ret : uint = rec(_N, 0, 0, 0, 1, 0);
            _sum += ret;
            
            var g : int = getTimer();
            tr(_p + "/" + _ptns.length, _ar, ret, (g - s) + "ms");
            
            _p++;
            if(_p == _ptns.length){
                removeEventListener(Event.ENTER_FRAME, onEnterFrame);
                tr(_sum);
            }
        }
        
        private var _ptns : Array;
        private var _p : uint;
        private var _sum : uint = 0;
        
        private function srec(left : int, acc : uint, _cur : Array, raw : uint) : Array
        {
            acc += raw - left;
            if(left == 0){
                return acc >= _M ? [_cur.concat()] : [];
            }
            var mod : int = left % 5;
            var i : uint;
            var ret : Array = [];
            for(i = 0;mod + 5*i <= 12 && mod + 5*i <= left;i++){
                ret = ret.concat(srec((left - (mod+5*i)) / 5, acc, _cur.concat(i), raw/5));
            }
            return ret;
        }
        
        private var _ar : Array;
        
        private function rec(left : int, a : uint, b : uint, c : uint, base : uint, pos : uint) : Number
        {
        	/*
            if(pos == _ar.length){
				return _C2[_N] - (_C2[a] + _C2[b] + _C2[c]) >= _M ? 1 : 0;
            }
            */
            
            var mod : int = left % 5;
            var i : uint = _ar[pos];
            var ret : Number = 0;
            
            var abc : Array;
            if(pos < _ar.length - 1){
	            var nb : uint = base * 5;
	            var nleft : uint = (left - (mod+5*i))/5;
	            for each(abc in _t5[mod+5*i]){
	                ret += rec(nleft, 
	                    a + abc[0] * base, 
	                    b + abc[1] * base,
	                    c + abc[2] * base,
	                    nb, pos + 1);
	            }
            }else{
	            for each(abc in _t5[mod+5*i]){
					if(_C2[_N] - (_C2[a + abc[0]*base] + _C2[b + abc[1] * base] + _C2[c + abc[2] * base]) >= _M){
						ret++;
					}
	            }
            }
            return ret;
        } 
        
        private function check(a : uint, d : uint) : uint
        {
            var ret : uint = 0;
            var i : uint;
            for(i = a / d;i > 0;i /= d)ret += i;
            return ret;
        }
        
        private function solve2(M : uint, N : uint) : Number
        {
        		var n5 : uint = check(N, 5);
        		var n2 : uint = check(N, 2);
        		var ct : uint = 0;
        		var o : Object = {};
        		for(var a : uint = 0;a <= N;a++){
        			for(var b : uint = 0;b <= N - a;b++){
        				var c : uint = N - a - b;
                		var j5 : uint = n5 - (check(a, 5) + check(b, 5) + check(c, 5));
                		var j2 : uint = n2 - (check(a, 2) + check(b, 2) + check(c, 2));
                		if(j5 >= M && j2 >= M){
//                		if(j5 >= M){
                			var aa : uint = a;
                			var bb : uint = b;
                			var cc : uint = c;
                			var re : Number = 0;
                			for(var nn : uint = N;nn > 0;nn /= 5, aa /= 5, bb /= 5, cc /= 5){
                				re = re * 100 + int(nn / 5) - (int(aa / 5) + int(bb / 5) + int(cc / 5));
                			}
                			if(!o[re])o[re] = 0;
                			o[re]++;
//                			tr(a, b, c);
                			ct++;
                		} 
        			}
        		}
        		
        		for(var key : String in o){
        			tr(key, o[key]);
        		}
        		return ct;
        }

        private function tr(...o : Array) : void
        {
            _tf.appendText(o + "\n");
            _tf.scrollV = _tf.maxScrollV;
        }
    }
}