Project Euler 210(unsolved)

by uwi
@see http://projecteuler.net/index.php?section=problems&id=210
♥0 | Line 107 | Modified 2010-03-12 11:42:30 | 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/fEUK
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // @see http://projecteuler.net/index.php?section=problems&id=210
    public class Euler210 extends Sprite {
        private var _tf : TextField;
  
        public function Euler210() {
            _tf = new TextField();
            _tf.width = 465;
            _tf.height = 465;
            addChild(_tf);
            
            var s : int = getTimer();
            tr(solve(100)); 
            tr(solveNaive(100)); 
            var g : int = getTimer();
            tr((g - s) + " ms");
        }

        private function solveNaive(r : Number) : Number
        {
        		var ct : uint = 0; 
        		var oc2 : Number = r*r/8;
        		for(var y : int = -r;y <= r;y++){
        			for(var x : int = -(r - Math.abs(y));x <= r - Math.abs(y);x++){
        				if(x == y)continue;
        				var ob2 : Number = x * x + y * y;
        				var bc2 : Number = (x-r/4)*(x-r/4)+(y-r/4)*(y-r/4);
        				if(ob2 == 0 || bc2 == 0)continue;
        				if(
        					ob2 + bc2 - oc2 < 0 ||
        					ob2 + oc2 - bc2 < 0 ||
        					oc2 + bc2 - ob2 < 0
        					){
    						if((x-r/8)*(x-r/8)+(y-r/8)*(y-r/8) <= r*r/32 && x < 0){
	        					ct++;
    						}
        				}
        			}
        		}
        		return ct;
        }
        
        // |x|+|y|<=rを満たす格子点で、
        // (0,0)と(r/4,r/4)と鈍角三角形をなすような格子点の個数をN(r)とするとき、
        // N(10^9)を求める。
        private function solve(r : Number) : Number
        {
        		var R : Number = r/8*Math.SQRT2;
        		var dsup : Number = -(r/8-R);
        		var sum : Number = 0;
        		var i : uint;
        		
        		var edge : Number;
        		for(i = 1;i <= dsup;i++){
//        			var sq : Number = Math.sqrt(R*R-(r/8+i)*(r/8+i));
// R*R-(r/8+i)*(r/8+i)=(r^2/64*2)-(r^2/64+r/4*i+i*i)
// 桁オーバーする・・
// r/8+√((√2(r/8))^2-(r/8+i)^2)=整数?
// =r/8+√(r^2/32-(r/8+i)^2)=1/2(r/4+√(r^2/8-(r/4+2i)^2)
// 625/2-(25/2+3)^2=625/2-961/4=289/4=>17/2
				var D : Number = r/4+Math.sqrt(r*r/8-(r/4+2*i)*(r/4+2*i));
				if(D / 2 == Math.floor(D / 2)){
					sum += Math.sqrt(r*r/8-(r/4+2*i)*(r/4+2*i))-1;
				}else{
					var sq : Number = Math.sqrt(R-(r/8+i))*Math.sqrt(R+(r/8+i));
	        			edge = r/8+sq;
//	        			tr(edge, sq); 
		        		sum += Math.floor(edge);
	        		
	        			edge = r/8-sq;
		        		sum -= Math.floor(edge);
				}
		     	tr(sum);
        		}
        		tr(sum);
        		sum = sum * 4 - (r/4+1)-2;
        		tr(sum);
        		
        		sum += (r/4+1)*(r/4+1);
        		tr(sum);
        		
        		// r*r/2
        		// r*r/2
        		sum += r*r;

       		// r*(r/2)/2
        		// r*(r/2)/2
    			sum += r*r/2;
        		tr(sum);
        		tr(dsup);
        		return sum;
        }

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

class N2{
	public static const N : Number = 1E15;	
	public static function add(a : Array, b : Array) : Array
	{
		var r0 : Number = a[0] + b[0];
		var rp : int = Math.floor(r0 / N);
		r0 -= rp * N;
		var r1 : Number = a[1] + b[1] + rp;
		return [r0, r1];
	}
	
	public static function sub(a : Array, b : Array) : Array
	{
		var r0 : Number = a[0] - b[0];
		var rp : int = Math.floor(r0 / N);
		r0 -= rp * N;
		var r1 : Number = a[1] - b[1] + rp;
		return [r0, r1];
	}
	
	public static function inc(a : Array, b : Number) : Array
	{
		var r0 : Number = a[0] + b;
		var rp : int = Math.floor(r0 / N);
		r0 -= rp * N;
		var r1 : Number = a[1] + rp;
		
		a[0] = r0;
		a[1] = r1;
		return a;
	}
}