# Paste: euler255 (crappy)

Author: Jon factor Thu, 17 Sep 2009 17:04:00
Plain Text |
```! Copyright (C) 2009 Jon Harper.
USING: project-euler.common math kernel sequences math.functions math.ranges prettyprint io threads math.parser locals arrays ;
IN: project-euler.255

! http://projecteuler.net/index.php?section=problems&id=255

! DESCRIPTION
! -----------
! We define the rounded-square-root of a positive integer n as the square root of n rounded to the nearest integer.
!
! The following procedure (essentially Heron's method adapted to integer arithmetic) finds the rounded-square-root of n:
!
! Let d be the number of digits of the number n.
! If d is odd, set x_(0) = 2×10^((d-1)⁄2).
! If d is even, set x_(0) = 7×10^((d-2)⁄2).
! Repeat:
!
! until x_(k+1) = x_(k).
!
! As an example, let us find the rounded-square-root of n = 4321.
! n has 4 digits, so x_(0) = 7×10^((4-2)⁄2) = 70.
!
! Since x_(2) = x_(1), we stop here.
! So, after just two iterations, we have found that the rounded-square-root of 4321 is 66 (the actual square root is 65.7343137…).
!
! The number of iterations required when using this method is surprisingly low.
! For example, we can find the rounded-square-root of a 5-digit integer (10,000 ≤ n ≤ 99,999) with an average of 3.2102888889 iterations (the average value was rounded to 10 decimal places).
!
! Using the procedure described above, what is the average number of iterations required to find the rounded-square-root of a 14-digit number (10^(13) ≤ n < 10^(14))?
!
! Note: The symbols ⌊x⌋ and ⌈x⌉ represent the floor function and ceiling function respectively.
!

! the number length function from project-euler.common doesn't work.

: sum-push ( elt vector -- )
[ pop  + ] keep push ;

: my-push ( elt vector -- )
dup empty? [ push ] [ sum-push ] if ; inline

: my-accumulator ( quot -- quot' vec )
V{ } clone [ [ my-push ] curry compose ] keep ; inline

: produce-sum ( pred: ( -- ? ) quot: ( -- elt ) -- sum )
my-accumulator [ while ] dip dup empty? [ drop 0 ] [ first ] if ; inline

: my-number-length ( i -- l ) number>string length ;

: x0 ( i -- x0 )
my-number-length dup even?
[ 2 - 2 / 10 swap ^ 7 * ]
[ 1 - 2 / 10 swap ^ 2 * ] if ;

: xk+1 ( n xk -- xk+1 )
[ / ceiling ] keep + 2 / floor ;

: next-multiple ( a multiple -- next )
[ [ 1 - ] dip /i 1 + ] keep * ;

DEFER: iteration#
:: f ( i xi a b -- iterations# )
a xi xk+1 dup xi =
[ drop i b a - 1 + * ]
[ i 1 + swap a b iteration# ] if ;

:: iteration# ( i xi a b -- # )
a a xi next-multiple
[ dup b < ]
[ [ nip [ 1 + ] [ xi + ] bi ] 2keep [ i xi ] 2dip f ] produce-sum
[ drop b [ i xi ] 2dip f ] dip
+ ;

: (euler255) ( a b -- answer )
[ 10 swap ^ ] [ 10 swap ^ 1 - ] bi*
[ [ drop x0 1 swap ] 2keep iteration# ] 2keep
swap - 1 + / >float ;

: euler255 ( -- answer )
13 14 (euler255) ;```

## Annotation: Faster

Author: jon factor Thu, 17 Sep 2009 18:59:54
Plain Text |
```! Copyright (C) 2009 Jon Harper.
USING: project-euler.common math kernel sequences math.functions math.ranges prettyprint io threads math.parser locals arrays namespaces ;
IN: project-euler.255

! http://projecteuler.net/index.php?section=problems&id=255

! DESCRIPTION
! -----------
! We define the rounded-square-root of a positive integer n as the square root of n rounded to the nearest integer.
!
! The following procedure (essentially Heron's method adapted to integer arithmetic) finds the rounded-square-root of n:
!
! Let d be the number of digits of the number n.
! If d is odd, set x_(0) = 2×10^((d-1)⁄2).
! If d is even, set x_(0) = 7×10^((d-2)⁄2).
! Repeat:
!
! until x_(k+1) = x_(k).
!
! As an example, let us find the rounded-square-root of n = 4321.
! n has 4 digits, so x_(0) = 7×10^((4-2)⁄2) = 70.
!
! Since x_(2) = x_(1), we stop here.
! So, after just two iterations, we have found that the rounded-square-root of 4321 is 66 (the actual square root is 65.7343137…).
!
! The number of iterations required when using this method is surprisingly low.
! For example, we can find the rounded-square-root of a 5-digit integer (10,000 ≤ n ≤ 99,999) with an average of 3.2102888889 iterations (the average value was rounded to 10 decimal places).
!
! Using the procedure described above, what is the average number of iterations required to find the rounded-square-root of a 14-digit number (10^(13) ≤ n < 10^(14))?
!
! Note: The symbols ⌊x⌋ and ⌈x⌉ represent the floor function and ceiling function respectively.
!

! the number length function from project-euler.common doesn't work.

: produce-sum ( pred quot -- sum )
[ 0 ] 2dip [ [ dip swap ] curry ] [ [ dip + ] curry ] bi* while ; inline

: my-number-length ( i -- l ) number>string length ;

: x0 ( i -- x0 )
my-number-length dup even?
[ 2 - 2 / 10 swap ^ 7 * ]
[ 1 - 2 / 10 swap ^ 2 * ] if ;

: xk+1 ( n xk -- xk+1 )
[ [ 1 - + ] keep /i ] keep + 2 /i ;

: next-multiple ( a multiple -- next )
[ [ 1 - ] dip /i 1 + ] keep * ;

DEFER: iteration#
:: f ( i xi a b -- iterations# )
a xi xk+1 dup xi =
[ drop i b a - 1 + * ]
[ i 1 + swap a b iteration# ] if ;

:: iteration# ( i xi a b -- # )
a a xi next-multiple
[ dup b < ]
[ [ nip [ 1 + ] [ xi + ] bi ] 2keep [ i xi ] 2dip f ] produce-sum
[ drop b [ i xi ] 2dip f ] dip
+ ;

: (euler255) ( a b -- answer )
[ 10 swap ^ ] [ 10 swap ^ 1 - ] bi*
[ [ drop x0 1 swap ] 2keep iteration# ] 2keep
swap - 1 + / >float ;

: euler255 ( -- answer )
13 14 (euler255) ;```

## Annotation: Java version

Author: Jon factor Thu, 17 Sep 2009 19:04:55
Plain Text |
```public class Euler255 {

static double totalcounts = 0;
public static void main(String[] args) {
long a = (long) Math.pow(10, 13);
long b = (long) Math.pow(10, 14)-1;
a = (long) Math.pow(10, 13);
b = (long) Math.pow(10, 14)-1;
long xzero = xzero((long) a);
long time = System.currentTimeMillis();
count(a,b,1,xzero);
System.out.println(totalcounts/(b-a+1));
System.out.println("Total Time :" + (System.currentTimeMillis()-time) + "ms");
}

public static long numberOfIteration(long n) {
long xk = xzero(n);
long nextxk = nextxk(n, xk);
int count = 1;
while(xk!=nextxk) {
xk = nextxk;
nextxk = nextxk(n,xk);
count++;
}
return count;
}

public static long xzero(long n) {
long d = numberOfDigits(n);
if (d%2 == 0) {
return (long) (7*Math.pow(10, (d-2)/2));
}
else {
return (long) (2*Math.pow(10, (d-1)/2));
}
}

public static long numberOfDigits(long n) {
long count=1;
while (n/10>0) {
count++;
n=n/10;
}
return count;
}

public static long nextxk(long n, long xk) {
double n1 = n;
double toto = n1/xk;
double tutu = Math.ceil(toto);
double trtr = tutu + xk;
double tata = trtr/2;
double tktk = Math.floor(tata);
long result = (long) tktk;
return result;
}

public static void count(long a,long b,int iter, long xk) {
long nexta = nextMultiple(a, xk);
long nextxk = nextxk(a,xk);

while (nexta<b) {
if (xk == nextxk) {
totalcounts+=iter*(nexta-a+1);
} else {
count(a,nexta,iter+1,nextxk);
}
a=nexta+1;
nexta= nexta+xk;
nextxk=nextxk(a,xk);
}

if (xk == nextxk) {
totalcounts+=iter*(b-a+1);
} else {
count(a,b,iter+1,nextxk);
}

}

public static long nextMultiple(long a, long multiple) {
return (((a-1)/multiple)+1)*multiple;
}
}```