Project Euler 226

by uwi
@see http://projecteuler.net/index.php?section=problems&id=226
♥0 | Line 81 | Modified 2009-10-25 15:34:54 | 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/aC4V
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // @see http://projecteuler.net/index.php?section=problems&id=226
    public class Euler226 extends Sprite {
        private var _tf : TextField;
  
        public function Euler226() {
            _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 function Sblancmange(seg : int, depth : int) : Number
        {
            var s : Number = 1.0 / (1 << (depth + 1));
            for(var i : int = 0;i < depth;i++){
                var pos : int = ((seg >> i) & 1) == 0 ? 
                    seg & ((1 << i) - 1) :
                    ((1 << i) - 1) - (seg & ((1 << i) - 1));
//                tr(i, pos);
                s += (pos + 0.5) / (1 << depth);
            }
            s /= (1 << depth);
            
            return s;
        }
        
        private function bla(x : Number) : Number
        {
            var f : Number = 0;
            var n2 : Number = 1;
            for(var n : int = 0;n < 50;n++){
                var d : Number = Math.round(n2 * x);
                d = d - n2 * x;
                if(d < 0)d = -d;
                f += d / n2;
                n2 *= 2;
            }
            return f;
        }
        
        private function solve() : Number
        {
            // 高木曲線と円の左側の交点のx座標を求める
            var start : Number = 0;
            var end : Number = 0.25;
            do{
                var mid : Number = (start + end) / 2;
                var f : Number = -(0.5 - Math.sqrt(0.25 * 0.25 - (0.25 - mid) * (0.25 - mid)));
                f += bla(mid);
                if(f < 0){
                    start = mid;
                }else{
                    end = mid;
                }
            }while(end - start > 0.00000000001);
            
            var s : Number = rec(start, 1, 1); // [x,0.5]の高木曲線の面積
            var minus : Number =  // [x, 0.5]の長方形から円をひいた面積
                (0.5 - mid) * 0.5 - // 長方形
                0.25 * 0.25 / 2 * (Math.asin((0.25 - mid) / 0.25) + Math.PI / 2) - // 扇形
                (0.25 - mid) * Math.sqrt(0.25 * 0.25 - (0.25 - mid) * (0.25 - mid)) / 2; // 残った三角形
            tr(mid, s, minus);
            return s - minus;
            
        }
        
        private function rec(start : Number, e : int, depth : int) : Number
        {
            if(depth == 31)return 0; 
            
            var n2 : Number = 1 << depth; // Math.pow(2, depth);
            var s : Number = start * n2;
            
            var ret : Number = 0;
            for(var i : int = Math.ceil(s);i < e;i++){
                ret += Sblancmange(i, depth);
            }
            return ret + rec(start, Math.ceil(s) * 2, depth + 1);
        }

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