Project Euler 289(unsolved)

by uwi
@see http://projecteuler.net/index.php?section=problems&id=
♥0 | Line 109 | Modified 2010-04-24 19:57:13 | 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/6CBb
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // @see http://projecteuler.net/index.php?section=problems&id=
    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(solve(1, 2));
            var g : int = getTimer();
            tr((g - s) + " ms");
        }

        private var _used : Array;
        private var m : uint;
        private var n : uint;
        private var _cross : Array;
        
        private function solve(m : uint, n : uint) : Number
        {
        	
        		this.m = m; this.n = n;
        		_used = new Array(m * n * 4);
        		_cross = new Array((m+1)*(n+1));
        		for(var i : uint = 0;i < _cross.length;i++){
        			_cross[i] = 0;
        		}
        		
        		return rec(0, 0, 0, 0);
        }
        
        private const LEFT : Array = [
        			4<<15|6<<9|0<<6|2<<0,
        			0<<15|2<<9|4<<6|6<<0
        		];
        private const RIGHT : Array = [
        			1<<21|3<<18|5<<12|7<<3,
        			5<<21|7<<18|1<<12|3<<3
        		];
        private const TOP : Array = [
        			0<<18|1<<9|3<<3|6<<0,
        			3<<18|6<<9|0<<3|1<<0
        		];
        private const BOTTOM : Array = [
        			5<<21|7<<15|2<<12|4<<6,
        			2<<21|4<<15|5<<12|7<<6
        		];
        private var INVRULE : Object = {};
        private const CROSS : Array = [
        			6<<21|7<<18|4<<15|5<<12|2<<9|3<<6|0<<3|1<<0,
        			6<<21|7<<18|5<<15|3<<12|4<<9|5<<6|0<<3|1<<0,
        			2<<21|3<<18|4<<15|5<<12|6<<9|7<<6|0<<3|1<<0,
        			2<<21|5<<18|6<<15|3<<12|4<<9|7<<6|0<<3|1<<0,
        			6<<21|7<<18|4<<15|5<<12|0<<9|1<<6|2<<3|3<<0,
        			4<<21|5<<18|6<<15|7<<12|0<<9|1<<6|2<<3|3<<0,
        			6<<21|7<<18|0<<15|3<<12|4<<9|1<<6|2<<3|5<<0,
        			6<<21|7<<18|0<<15|1<<12|2<<9|3<<6|4<<3|5<<0,
        			0<<21|5<<18|6<<15|3<<12|4<<9|1<<6|2<<3|7<<0,
        			0<<21|5<<18|6<<15|1<<12|2<<9|3<<6|4<<3|7<<0,
        			0<<21|1<<18|4<<15|5<<12|2<<9|3<<6|6<<3|7<<0,
        			0<<21|1<<18|2<<15|3<<12|4<<9|5<<6|6<<3|7<<0
        		];
        
        // (x,y)
        // arc:下から反時計周り
        private function rec(x : uint, y : uint, arc : uint, dir : uint) : Number
        {
        		if(x == 0 && y == 0 && arc == 3 && dir == 0)return 1;
        		var code : uint = (x*n+y)*m+arc;
        		if(_used[code] == 1)return 0;
        		_used[code] = 1;
        		var ret : Number = 0;
        		
        		// 1
        		if(x == 0 && y == n - 1 && arc == 2 && dir == 0){ret = rec(x, y, 3, 0); _used[code] = 0; return ret;}
        		if(x == 0 && y == n - 1 && arc == 3 && dir == 1){ret = rec(x, y, 2, 1); _used[code] = 0; return ret;}
        		if(x == m - 1 && y == 0 && arc == 0 && dir == 0){ret = rec(x, y, 1, 0); _used[code] = 0; return ret;}
        		if(x == m - 1 && y == 0 && arc == 1 && dir == 1){ret = rec(x, y, 0, 1); _used[code] = 0; return ret;}
        		if(x == m - 1 && y == n - 1 && arc == 1 && dir == 0){ret = rec(x, y, 2, 0); _used[code] = 0; return ret;}
        		if(x == m - 1 && y == n - 1 && arc == 2 && dir == 1){ret = rec(x, y, 1, 1); _used[code] = 0; return ret;}
        		
        		var indir : uint = [7, 1, 3, 5, 2, 4, 6, 0][dir*4+arc];
        		var tx : uint = x + [1, 1, 0, 0, 0, 1, 1, 0][dir*4+arc];
        		var ty : uint = y + [0, 1, 1, 0, 0, 0, 1, 1][dir*4+arc];
        		var tc : uint = tx*(n+1)+ty;
        		tr(x, y, arc, dir, tx, ty);
        		
        		// 2
        		var p : uint;
        		var o : uint;
        		var ndir : uint, nx : uint, ny : uint, narc : uint;
        		
        		var set : Array = CROSS;
        		if(tx == 0)set = LEFT;
        		if(ty == 0)set = BOTTOM;
        		if(tx == m)set = RIGHT;
        		if(ty == n)set = TOP;
   			for each(p in set){
        			if((_cross[tc] | p) == p){
        				narc = (p >> (3*indir)) & 7;
        				o = _cross[tc];
        				_cross[tc] |= narc << (3*indir) | indir << (3*narc);
        				ndir = dir ^ ((indir - narc) % 2 == 0 ? 1 : 0); 
					nx = tx - [1, 1, 0, 0, 0, 1, 1, 0][ndir*4+narc];
					ny = ty - [0, 1, 1, 0, 0, 0, 1, 1][ndir*4+narc];
        				ret += rec(nx, ny, narc, ndir);
        				_cross[tc] = o;
        			}
    			}
    			_used[code] = 0;
        		return ret;
        }

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