Project Euler #80: Square root digital expansion

Sort by

recency

|

21 Discussions

|

  • + 0 comments

    My Solution in python

    from decimal import Decimal,getcontext def sum_of_digits(n,p): getcontext().prec=p+5 sqrt_str=str(Decimal(n).sqrt()).replace('.','')[:p] return sum(int(digit) for digit in sqrt_str) def main(): N= int(input().strip()) P= int(input().strip()) total_sum= sum(sum_of_digits(i,P) for i in range (1,N+1) if int (i**0.5)**2 != i) print(total_sum) if name=="main": main()

  • + 0 comments

    Python 3 solution:

    import decimal
    n=int(input().strip())
    p=int(input().strip())
    decimal.getcontext().prec=p+4
    total=0
    for i in range(2,n+1):
        if int(i**0.5)!=i**0.5:
            digits=list(str(decimal.Decimal(i).sqrt()))[:p+1]
            digits.remove('.')
            #print(len(digits))
            total+=sum(map(int,digits))
    print(total)
            
    
  • + 0 comments

    Finally solved this problem after a lot of efforts. Approach:

    • use Newton-Raphson method for calculating square roots. Apparently it's faster than digit by digit calculation.
    • use language built-in sqrt method to initialize Newton-Raphson variables to speed things up. NB: for Java and .NET the last digit of Math.sqrt can be off, so take this into account when setting the initial values of the Newton-Raphson variables.
    • use language built-in BigInteger to store square root digits. I do this by for example not calculating the square root of 2, but the square root of 20000 if 3 digits of sqrt(2) are necessary.
    • cache all calculated square roots
    • only use Newton-Raphson to calculate the square roots of prime numbers.
    • for numbers which are squares, calculate the square root the easy way. And don't store lots of trailing zeros, since these don't add anything to the digit sum in the end.
    • for all other numbers, multiply two already calculated square roots. But choose carefully and prefer multiplying a simple square root over multiplying two long square roots (example: sqrt(12) = 2 * sqrt(3) is faster than sqrt(12) = sqrt(2) * sqrt(6) )
    • calculate some extra digits (say 10) to make sure that multiplication etc doesn't lead to wrong answers
    • of course, when summing the final answer, only look at the requested number of digits
    • use BigInteger.toString() to get all the digits. This is faster than calculating them in some other ways.

    With F# (so .NET), this approach solves all test cases but the last one. With java, this exact same approach solves all test cases (test case 9 takes 3 seconds).

    I'm disappointed to see that all my efforts to solve this problem in F# have failed. I see that some people managed to solve this problem with C#, so it could be that another approach than mine would be fast enough also in F#.

    Good luck!

  • + 0 comments

    import decimal num=decimal.Decimal(int(input())) dot100 = decimal.Context(prec=10000) num=num.sqrt(dot100) num=str(num) precision=int(input()) sum1=x=i=0 while num[i]!=".": i=i+1 num=num[:i]+num[i+1:] num=num[0:precision] print(sum([int(x) for x in num]))

    this is my code i am passing only the first test condition

  • + 0 comments

    You only need to compute the square roots of prime numbers, because the square root of a composite number c is the product of the square roots of its prime factors.

    E.g. for c=12: sqrt(12) = sqrt(2*2*3) = sqrt(2) * sqrt(2) * sqrt(3)

    Actually you don't need a full factorization. Choose any two factors a and b where ab=c: sqrt(12) = sqrt(3) * sqrt(4) (or sqrt(2) * sqrt(12))

    You need to be a bit careful, though: a factor can be a perfect square (such as 4), therefore memoize all (!) square roots, even the trivial ones of perfect squares. And even more, you have to increase your precision by a few digits because you'll introduce some rounding errors when multiplying. Adding 15 extra digits is more than enough.

    After I added this trick to my code it became about 4x faster for N=100 and P=10000.