Project Euler 270(unsolved)

by uwi
TODO C(3)を全数チェック
@see http://projecteuler.net/index.php?section=problems&id=
♥0 | Line 127 | Modified 2009-12-29 02:03:05 | 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/t5iv
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // TODO C(3)を全数チェック
    // @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());
            var g : int = getTimer();
            tr((g - s) + " ms");
        }
        
        private var _cache : Array;
        private const N : uint = 2;

        private function solve() : Number
        {
            _cache = makeArray(N+1, N+1, N+1, N+1, 8);
            
            var ret : Number = 0;
            // 左上隅, 左下隅がアクティブ(台形)
            var sum : Number = 0;
            var i : uint, j : uint;
            for(i = 1;i < N;i++){
                for(j = i;j < N;j++){
                    sum += (rec(N, 0, 0, i) * rec(0, 0, N, N - j) * rec(0, N, 0, j - i + 1)) % 100000000;
                }
            }
            tr(1, sum);
            ret += sum * 4;
            
            // 左上隅、右下隅がアクティブ(台形)
            sum = 0;
            for(i = 1;i < N;i++){
                for(j = 1;j < N;j++){
                    //                       隅を削る
                    sum += (rec(N, 0, 0, i) * rec(0, j, 0, N - i) * rec(0, N - i, N, 0)) % 100000000;
                }
            }
            tr(2, sum);
            ret += sum * 4;
            
            // 左上隅、右下隅がアクティブ(対角線)
            sum = (rec(N, 0, 0, N) * rec(0, N, N, 0)) % 100000000;
            tr(3, sum);
            ret += sum * 2;
            
            // 左上隅だけがアクティブ
            sum = 0;
            for(i = 1;i < N;i++){
                sum += (rec(N - 1, 0, 0, i) * rec(0, N - 1, N - 1, N - i)) % 100000000;
            }
            sum *= 2;
            for(i = 1;i < N;i++){
                for(j = 1;j < N;j++){
                    sum += (rec(N - 1, 0, 0, i) * rec(0, N - 1, j, 0) * rec(0, 0, N - j, N - i)) % 100000000;
                }
            }
            tr(4, sum);
            ret += sum * 4;
            
            // すべてノンアクティブ
            sum = rec(N - 1, N - 1, N - 1, N - 1);
            tr(5, sum);
            ret += sum;
            return ret % 100000000;
        }
        
        // NESW
        private function rec(a : uint, b : uint, c : uint, d : uint, prev : uint = 0) : Number
        {
//            tr(a, b, c, d, prev);
            if(a + b + c + d <= 1)return 0;
            if(a + b + c + d <= 3)return 1;
            
            var ret : Number = 0;
            var x : uint, y : uint, z : uint, w : uint;
            
            if(_cache[a][b][c][d][prev] != null){
//                tr(a,b,c,d,prev,_cache[a][b][c][d][prev]);
                return _cache[a][b][c][d][prev];
            }
            
            /*
            if(b == 0 && d == 0){
                ret = C(a + c, c);
            }else if(a == 0 && c == 0){
                ret = C(b + d, d);
            }else 
            }else{
                */
            // a-b
            x = a; y = b; z = c; w = d;
            if(prev <= 0){
                if((x >= 3 && y >= 1) || (x >= 2 && y >= 2) || (x == 2 && y == 1 && (z > 0 || w > 0)))ret = (ret + rec(a - 1, b, c, d, 0)) % 100000000;
                if((y >= 3 && x >= 1) || (y >= 2 && x >= 2) || (y == 2 && x == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b - 1, c, d, 0)) % 100000000;
            }
            
            // b-c
            x = b; y = c; z = d; w = a;
            if(prev <= 1){
                if((x >= 3 && y >= 1) || (x >= 2 && y >= 2) || (x == 2 && y == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b - 1, c, d, 1)) % 100000000;
                if((y >= 3 && x >= 1) || (y >= 2 && x >= 2) || (y == 2 && x == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b, c - 1, d, 1)) % 100000000;
            }
            
            // c-d
            x = c; y = d; z = a; w = b;
            if(prev <= 2){
                if((x >= 3 && y >= 1) || (x >= 2 && y >= 2) || (x == 2 && y == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b, c - 1, d, 2)) % 100000000;
                if((y >= 3 && x >= 1) || (y >= 2 && x >= 2) || (y == 2 && x == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b, c, d - 1, 2)) % 100000000;
            }
            
            // d-a
            x = d; y = a; z = b; w = c;
            if(prev <= 3){
                if((x >= 3 && y >= 1) || (x >= 2 && y >= 2) || (x == 2 && y == 1 && (z > 0 || w > 0)))ret = (ret + rec(a, b, c, d - 1, 3)) % 100000000;
                if((y >= 3 && x >= 1) || (y >= 2 && x >= 2) || (y == 2 && x == 1 && (z > 0 || w > 0)))ret = (ret + rec(a - 1, b, c, d, 3)) % 100000000;
            }
            
            if(prev <= 4){
                if(a == 1 && b == 1 && c == 1 && d == 1){
                    ret = 2;
                }else if(a <= 1 && c <= 1){
                    ret = C(b + d, d);
                }else if(b <= 1 && d <= 1){
                    ret = C(a + c, c);
                }
            }
            /*
            if(prev <= 4 && a >= 1 && c >= 1 && b == 1)ret = (ret + rec(a, 0, c, d, 4)) % 100000000;
            if(prev <= 5 && a >= 1 && c >= 1 && d == 1)ret = (ret + rec(a, b, c, 0, 5)) % 100000000;
            if(prev <= 6 && b >= 1 && d >= 1 && c == 1)ret = (ret + rec(a, b, 0, d, 6)) % 100000000;
            if(prev <= 7 && b >= 1 && d >= 1 && a == 1)ret = (ret + rec(0, b, c, d, 7)) % 100000000;
            */
            
            /*
            // a-c, b-d
            if(ret == 0){
                if(a >= 2 && c >= 1 && (b == 0 || d == 0))ret = (ret + rec(a - 1, b, c, d, 4)) % 100000000;
                if(c >= 2 && a >= 1 && (b == 0 || d == 0))ret = (ret + rec(a, b, c - 1, d, 5)) % 100000000;
                if(b >= 2 && d >= 1 && (a == 0 || c == 0))ret = (ret + rec(a, b - 1, c, d, 6)) % 100000000;
                if(d >= 2 && b == 1 && (a == 0 || c == 0))ret = (ret + rec(a, b, c, d - 1, 7)) % 100000000;
                if(a == 1 && c == 1 && b == 1 && d == 1)ret = (ret + 2) % 100000000;
            }
            */
            
            _cache[a][b][c][d][prev] = ret;
            
            return ret;
        }
        
        private function C(n : uint, k : uint) : Number
        {
            var mul : Number = 1;
            for(var i : uint = 1;i <= k;i++){
                mul *= n - i + 1;
                mul /= i;
            }
            return mul;
        }
        
        private function makeArray(...o : Array) : Array
        {
            var l : uint = o.shift();
            var ret : Array = new Array(l);
            if(o.length > 0){
                for(var i : uint = 0;i < l;i++){
                    ret[i] = makeArray.apply(null, o);
                }
            }
            return ret;
        }

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