Project Euler 275(unsolved)

by uwi
@see http://projecteuler.net/index.php?section=problems&id=275
♥0 | Line 172 | Modified 2010-01-24 01:07:43 | 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/prbU
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // @see http://projecteuler.net/index.php?section=problems&id=275
    public class Euler275 extends Sprite {
        private var _tf : TextField;
  
        public function Euler275() {
            _tf = new TextField();
            _tf.width = 465;
            _tf.height = 465;
            addChild(_tf);
            
            var s : int = getTimer();
            _cache = new Array((1 << 16) * 13);
//            tr(recBuild((1 << 1) - 1, 8).length);
//            tr(solve(6));

//            _b = makeArray(0, 8, 16);
            _dic = makeArray([], 13);
            _b = [];
//            _b[0][0] = 1;
            _b.push(0, 0);
            _b.push(0, 2);
            recBuild();
            
            for(var i : uint = 0;i < 13;i++){
                tr(i, _dic[i].length);
            }
            
            // TODO 連結性判定
            
            var g : int = getTimer();
            tr((g - s) + " ms");
            tr(_ct);
        }
        
        public function makeArray(val : *, ...rest) : Array
        {
            if(rest.length == 0)return null;
            if(rest.length == 1){
                return fill(val, new Array(rest[0]));
            }else{
                var s : uint = rest.shift();
                var args : Array = [val].concat(rest);
                var ret : Array = new Array(s);
                for(var i : uint = 0;i < s;i++)ret[i] = makeArray.apply(null, args);
                return ret;
            }
        }
        
        // シャローコピーのfill
        public function fill(v : *, a : Array) : Array
        {
            for(var i : uint = 0;i < a.length;i++){
                if(v is Array){
                    a[i] = v.concat();
                }else{
                    a[i] = v;
                }
            }
            return a;
        }
                
        private var _b : Array;
        private var _dic : Array;
        private var _ct : int = 0;
        
        private function recBuild() : void
        {
            _ct++;
            if(_b.length == 24)return;
            
            var i : uint, j : uint, k : uint;
            var code : Array = [0, 0, 0, 0, 0, 0, 0, 0];
            for(i = 0;i < _b.length;i+=2){
                code[_b[i]] |= 1 << _b[i+1];
            }
            
            var n : uint = _b.length / 2;
            var bs : int = binarySearch(code, _dic[n], compArray);
            if(bs >= 0)return;
            _dic[n].splice(-bs-1, 0, code);
            
            for(i = 0;i < _b.length;i+=2){
                for each(var d : Array in DIR){
                    var x : int = _b[i] + d[0];
                    var y : int = _b[i+1] + d[1];
                    if(x <= 0 || y < 0 || y >= 16 || x >= 8)continue;
                    for(j = 0;j < _b.length && !(_b[j] == x && _b[j+1] == y);j+=2);
                    if(j == _b.length){
                        _b.push(x, y);
                        recBuild();
                        _b.pop(); _b.pop();
                    }
                }
            }
        }
        
        private function compArray(a : Array, b : Array) : int
        {
            for(var i : uint = 0;i < a.length;i++){
                if(a[i] != b[i]){
                    return a[i] - b[i];
                }
            }
            return 0;
        }
        
        private function binarySearch(c : Array, a : Array, comp : Function) : int
        {
            if(a.length == 0)return -1;
            var s : uint = 0;
            var e : uint = a.length;
            var m : uint = (s + e) >>> 1;
            for(;m - s >= 1;m = (s + e) >>> 1){
                var cr : int = comp(c, a[m]);
                if(cr == 0)return m;
                if(cr < 0){
                    e = m;
                }else{
                    s = m;
                }
            }
            cr = comp(c, a[s]);
            if(cr == 0)return s;
            if(cr > 0)return -2 - s;
            return -1 - s;
        }
        
        private const DIR : Array = [[1, 0], [0, 1], [-1, 0], [0, -1]];
        
        private var _cache : Array;

        private function solve(N : uint) : Number
        {
//            _cache = new Array((1 << lim) * n);
            var ret : Number = 0;
            for(var i : uint = 1;i < 1 << N;i++){
                var c : uint = countBit(i);
//                var h : uint = highestBit(i);
                var rss : Array = [];
                for(var j : uint = 0;j <= N - c;j++){
                    rss.push(recSide(i, j, 1, 16));
                }
                
                for(j = 0;j <= (N - c) / 2;j++){
                    for(var k : uint = 0;k < 37;k++){
                        if(rss[j][k] != null && rss[N-c-j][k] != null){
                            ret += rss[j][k] * rss[N - c - j][k];
                        }
                    }
                }
                // TODO それぞれの連結性チェック
                // TODO 中央との連結性チェック
            }
            return ret;
        }
        
        private function highestBit(n : uint) : uint
        {
            for(var i : uint = n, j : uint = 0;i > 0;i >>= 1, j++);
            return j;
        }
        
        private function side(n : uint, lim : uint) : Array
        {
            return recSide((1 << lim) - 1, n, 1, lim);
        }
        
        // ret[weight] = count
        private function recSide(prev : uint, left : uint, weight : uint, lim : uint) : Array
        {
            if(left == 0)return [1];
            var sup : uint = 1 << lim;
            
            /*
            if(_cache[left * sup + prev]){
                return _cache[left * sup + prev];
            }
            */
            
            var ret : Array = new Array(37);
            var i : uint;
            for(i = 0;i < 37;i++)ret[i] = 0;
            for(i = 0;i < sup;i++){
                var c : uint = countBit(i);
                if(c > left)continue;
                if((prev & i) == 0)continue;
                var rs : Array = recSide(i, left - c, weight + 1, lim);
                for(var j : uint = 0;j < rs.length;j++){
                   ret[j + c * weight] += rs[j];
                }
            }
            
//            _cache[left * sup + prev] = ret;
            return ret;
        }
        
        /*
        private function recBuild(prev : uint, left : uint) : Array
        {
            if(left == 0)return [[]];
            
            if(_cache[prev * 12 + left]){
                return _cache[prev * 12 + left];
            }
            
            var h : uint = highestBit(prev) + left - 1;
            h = 1 << h;
            
            var ret : Array = [];
            for(var i : uint = 0;i < h;i++){
                var c : uint = countBit(i);
                if(c > left)continue;
                if((prev & i) == 0)continue;
                if(left > c){
                    var rb : Array = recBuild(i, left - c);
                    for each(var r : Array in rb){
                        ret.push([i].concat(r));
                    }
                }else{
                    ret.push([i]);
                }
            }
            
            _cache[prev * 12 + left] = ret;
            
            return ret;
        }
        */
        
        private function countBit(n : uint) : uint
        {
            n = (n & 0x55555555) + (n >> 1 & 0x55555555);
            n = (n & 0x33333333) + (n >> 2 & 0x33333333);
            n = (n & 0x0f0f0f0f) + (n >> 4 & 0x0f0f0f0f);
            n = (n & 0x00ff00ff) + (n >> 8 & 0x00ff00ff);
            n = (n & 0x0000ffff) + (n >> 16 & 0x0000ffff);
            return n;
        }

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