Calculate the square root only using ++

13

5

Your task is to calculate the square root of a positive integer without using any mathematical operators to change the number, such as:

  • Setting a variable (ex. squareRoot = 5)
  • Addition (A+B)
  • Subtraction (A-B)
  • Multiplication (A*B)
  • Division (A/B)
  • Square, cube, fourth, etc. roots
  • Exponents

Comparison operators (such as <, >, ==, etc) are not considered "mathematical operators" for the purposes of this question and are allowed as long as they do not change the value of a variable.

The only operator that you are able to use is ++. The following exceptions are in place:

  • If you wish, you may initialize a variable by setting it to 0.
  • If your language does not include the ++ syntax, you may use an equivalent syntax, such as foo+=1 or foo=foo+1
  • The square root should be calculated to at least 6 digits beyond the decimal (the hundred-thousands place) and outputted as a whole number of the decimals (ex. if I input 2 it could come out as 14142135624 or 1414213 depending on the rounding). Rounding up or down is not important.

User-defined functions are not allowed. In addition, simulating functions with goto is not allowed as well.

I'm interested to see what everyone submits! Happy coding!

CLARIFICATION

Clarify that number is a positive integer. You are welcome to make code that would do any number but it is not necessary.

CLARIFICATION #2

Clarify that comparison operators are allowed.

CLARIFICATION #3

Addition, subtraction, multiplication, division, and functions to change numbers are not allowed at all, regardless of whether they are saved to a variable or not. I'm sorry that this invalidates a couple existing answers, but I meant to define this group of operators with "change the number" in order to prevent troll answers (ex. I just used the sqrt() function, you only prohibited addition, multiplication, division, and subtraction). Sorry for the confusion.

CLARIFICATION #4

Clarify that we need at least 5 digits. 10 digits caused code to run for a long time.

iggyvolz

Posted 2014-06-06T01:47:37.677

Reputation: 187

Are comparisons such as < and > disallowed operators? – Greg Hewgill – 2014-06-06T02:06:23.423

Comparisons are fine, however the only operation that can change the value of a variable (or constant, I suppose) are ++ and --, with the exceptions listed above. – iggyvolz – 2014-06-06T02:07:58.660

Are bitwise operators allowed? And to clarify, is -- allowed or not... as it isn't stated in the question, but in your comment you mentioned it. – Οurous – 2014-06-06T02:12:20.123

1Nope, -- is not allowed, sorry for the confusion! I originally planned to have ++ and -- but I decided to take -- out at the last minute. – iggyvolz – 2014-06-06T02:15:01.417

@iggyvolz ... and bitwise? – Οurous – 2014-06-06T02:20:33.217

5"without using any mathematical operators to change the number" - I think this might need clarification. Do you mean that these operators may not be used at all, or, that they may be used, but only if the result isn't saved to a variable, e.g. while r*r<n*10e20:r+=1 - fairly trivial. Also, you might consider reducing the required output to 10^8 or so. First, because 10^10 is larger than 2^31, and second, because it will take a while to increment that high. – primo – 2014-06-06T02:56:07.127

1Why would you ever want to "change" any variable at all? You imperative guys have strange ways of thinking... – ceased to turn counterclockwis – 2014-06-06T10:20:50.230

Are we allowed to do, say, i=1? That is, can we initialise a variable that will then be incremented? – Glen O – 2014-06-06T14:24:17.643

@leftaroundabout 'static variable' is self-contradictive. – primo – 2014-06-06T16:57:37.940

@Ourous - oh sorry, missed that part. If the function in itself changes the value of any variable, it is not allowed. – iggyvolz – 2014-06-06T19:56:57.933

@primo - I'll reduce it to 10^8, but answers with 10^10 will still be allowed – iggyvolz – 2014-06-06T20:00:04.930

@GlenO - "If you wish, you may initialize a variable by setting it to 0." You can do i=0, but not i=1. If you needed i=1, you could always do i=0;i++; – iggyvolz – 2014-06-06T20:00:58.313

4I am flagging to close this question. To much radical changes to the question. You should actually get this question validated through Sandbox or else you would frustrate people investing effort to answer. – Abhijit – 2014-06-06T20:21:08.797

3Reducing the number of required digits is meaningless without time/memory limits. My code can handle 5 digits, but my machine doesn't have enough RAM. – Dennis – 2014-06-07T02:11:51.227

Answers

13

Python 66

print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real

Output

>>> print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real
121
110000000000
>>> print'%.0f'%reduce(lambda a,b:abs(a)+1e10j,range(-2,input())).real
1000
316227766017

This solution uses Spiral of Theodorus on a complex plane to achieve the result.

Abhijit

Posted 2014-06-06T01:47:37.677

Reputation: 2 841

2I think that will need to be wrapped in int(...*1e10), otherwise very nice. Although, taking abs of a complex value is more or less sqrt in disguise. – primo – 2014-06-06T09:16:54.503

1@primo I don't think you're allowed the *1e10 ... – Cruncher – 2014-06-06T14:54:05.937

@primo: Instead of multiplying by 1e10, I took a bit different route. And though I agree that abs may be sqrt in disguise, yet I feel its completely legal as currently stated in the problem. – Abhijit – 2014-06-06T15:13:45.593

I see a downvote, and its quite depressing. I had high hope for this answer, so any one who downvoted, please leave back a comment. – Abhijit – 2014-06-06T19:49:03.683

This doesn't follow the new clarification. Sorry about invalidating your answer, but I meant to say that these functions were not allowed at all, not just to modify a variable. – iggyvolz – 2014-06-06T20:14:32.373

9@iggyvolz: I am really surprised that you keep on expanding your question and adding more restrictions. People invest time and effort to write an answer and you can;t expect them to be psycic. – Abhijit – 2014-06-06T20:19:30.493

I tried running as a py file and it says syntax error. In the interpreter it runs OK. Output without %d is 1.1e+11 and with %d output is 1099999999. – bacchusbeale – 2014-06-07T00:27:03.100

@bacchusbeale: I tried running as a py file and it says syntax error., not sure what error you are getting. This runs fine in ideone. Regarding, your o/p as 1099999999, there was a rounding issue which I have now fixed.

– Abhijit – 2014-06-07T06:09:18.287

6

Python, 184 characters

The following Python solution uses only the increment operator and no other arithmetic operators at all. However, with the required precision (10 digits), it takes an impossibly long time to run. You can test it with lower precision (3 digits) by reducing 1e20 to 1e6.

import sys;t=0
for _ in range(int(sys.argv[1])):
 for _ in range(int(1e20)):t+=1
q=0
while 1:
 z=0
 for _ in range(q):
  for _ in range(q):z+=1
 if z>=t:break
 q+=1
print(q)

Ungolfed:

import sys

# t = N * 100000000000000000000 (magnitude of twice the precision)
t = 0
for _ in range(int(sys.argv[1])):
    for _ in range(int(1e20)):
        t += 1
q = 0
while True:
    # z = q * q
    z = 0
    for _ in range(q):
        for _ in range(q):
            z += 1
    if z >= t:
        break
    q += 1
print(q)

Greg Hewgill

Posted 2014-06-06T01:47:37.677

Reputation: 2 641

I clarified the question, you can do it to as many digits as you want (at least 5).

I'm not familiar with python, but I'm assuming that int() is just a type caster? If so, that is fine because it doesn't change the value of the number. – iggyvolz – 2014-06-06T20:13:13.210

@iggyvolz: Right, you need that to convert the string argument value (specified on the command line) to an integer. A plain function wouldn't need that. – Greg Hewgill – 2014-06-07T04:13:04.703

2

Fortran 73

read*,t;s=0;do while(abs(s*s/1e10-t)>1e-10);s=s+1;enddo;print*,s/1e5;end

Might take a loooong to actually determine an answer for certain values, but it'll work for sure. While I use * and -, these are not changing any values, only the s=s+1 actually changes anything.

Kyle Kanos

Posted 2014-06-06T01:47:37.677

Reputation: 4 270

Wow, guess I didn't think about using operators for changing static values. That's perfectly fine and +1 (if I had 15 reputation to upvote) – iggyvolz – 2014-06-06T02:17:15.503

This uses the * operator, which is pretty clearly not permitted. Or am I somehow misunderstanding the given restrictions? – Greg Hewgill – 2014-06-06T02:20:44.527

@GregHewgill: OP states, without using any mathematical operators to change the number; these operators are not changing any values. – Kyle Kanos – 2014-06-06T02:21:36.013

I guess then I don't understand what is meant by the number - which number? Just the one that is the input to the program? – Greg Hewgill – 2014-06-06T02:22:45.827

@GregHewgill: We're to compute sqrt(t) by only incrementing some other variable, s, until s*s=t; my assumption is that "number" means s. – Kyle Kanos – 2014-06-06T02:24:08.790

7But that's still using the * operator to change a number, you're just not saving the result anywhere. If the OP wanted to simply disallow assignments (other than s=s+1), then why mention all the disallowed arithmetic operators? – Greg Hewgill – 2014-06-06T02:30:01.273

@GregHewgill: Nothing I did is explicitly against the specs, though I agree I'm bending it a little. OP said my answer is perfectly fine (because he didn't think about using operators for changing static values), I'm content with that. – Kyle Kanos – 2014-06-06T02:40:22.457

So then what does changing static values mean? The usual definition of static means that something doesn't change. What are you changing that doesn't change? – Greg Hewgill – 2014-06-06T02:43:02.030

@GregHewgill: I think that the question is poorly specified; this answer of mine reflects the poor nature of the question by abusing one aspect of the rules (that you can only change a variable by incrementing it). Any analysis of this particular answer is moot, IMO. – Kyle Kanos – 2014-06-06T12:42:26.233

This doesn't follow the new clarification. Sorry about invalidating your answer, but I meant to say that these functions were not allowed at all, not just to modify a variable.

Yeah, sorry about my earlier comment, I was half asleep when I made that. – iggyvolz – 2014-06-06T20:15:45.577

1

@iggyvolz: Changing the rules ~20 hours later is bad form. Please do not do that and use the sandbox to work out the kinks in your problem instead.

– Kyle Kanos – 2014-06-06T20:33:47.920

2

CJam, 26 bytes

q~,1e20,m*,:N!{)_,_m*,N<}g

Try it online. Paste the Code, type the desired integer in Input and click Run. Before you do, I suggest changing 1e10 to 1e4 though.

The Java interpreter handles 1e6 with input “2” in about 15 seconds. 1e20 will require a huge amount of RAM.

Examples

$ cjam <(echo 'q~,1e2,m*,:N!{)_,_m*,N<}g') <<< 4; echo
20
$ cjam <(echo 'q~,1e2,m*,:N!{)_,_m*,N<}g') <<< 2; echo
15
$ cjam <(echo 'q~,1e4,m*,:N!{)_,_m*,N<}g') <<< 4; echo
200
$ cjam <(echo 'q~,1e4,m*,:N!{)_,_m*,N<}g') <<< 2; echo
142
$ cjam <(echo 'q~,1e6,m*,:N!{)_,_m*,N<}g') <<< 4; echo
2000
$ cjam <(echo 'q~,1e6,m*,:N!{)_,_m*,N<}g') <<< 2; echo
1415

Background

Since we're not allowed mathematical operators to change numbers, we're going to use setwise operators to change arrays.

The code starts by "multiplying" the input (“i”) by 1e20, but without any actual multiplication. Instead, we push an array containing “i” integers, an array containing 1e20 integers, take their cartesian product and compute its length.

Then, we push zero and increment until the product of the integer by itself (calculated as above) is no longer smaller than i * 1e20. This causes the square root to be rounded up.

How it works

q~     " Read for STDIN and interpret. ";
,      " Push an array containing that many integers. ";
1e20,  " Push the array [ 0   …   1e20 - 1]. ";
m*,:N  " Get the length of the cartesian product and save it in “N”. ";
!      " Logical NOT. Since the input is a positive integer, this pushes 0. " ;
{      " ";
  )    " Increment the integer on the stack.";
  _,   " Push an array containing that many integers. ";
  _m*, " Get the length of the cartesian product of the array by itself. ";
  N<   " If the product is smaller than the target value, push 1; otherwise push 0. ";
}g     " Repeat the loop if the result was 1. ";

Dennis

Posted 2014-06-06T01:47:37.677

Reputation: 196 637

1

Cobra - 62

Posted before the third edit, no longer valid.

Not only is it short, but it should be overflow-free if n < Decimal.maxValue

def f(n)
    r,e=0d,10000000000
    while r/e*r/e<n,r+=1
    print r

Οurous

Posted 2014-06-06T01:47:37.677

Reputation: 7 916

But you used r/e*r/e, which is clearly a non-++ math operator... – nneonneo – 2014-06-08T02:19:42.247

@nneonneo this was posted before the third edit, and I haven't changed it yet – Οurous – 2014-06-08T03:28:19.750

0

Scala, 117

val z=BigInt(readLine+"0000000000")
print(Stream.from(1)find(x=>(BigInt(0)/:Stream.fill(x,x)(1).flatten){_+_}>=z)get)

Doesn't finish in a reasonable amount of time, even for 2 as input, but it does work. You may notice that I'm doing _+_, but that only ever adds 1, and Scala doesn't have a ++ operator anyway. I could save two characters by replacing the inner Stream with List, but then it would run out of memory. As written, I think it scales only in processing time, not memory usage.

Joe K

Posted 2014-06-06T01:47:37.677

Reputation: 1 065

0

PHP, 124 bytes

It's an exhaustive algorithm. It just tries numbers until the square of that number is bigger than the "goal" number (which is the input times 1Enumber of decimals squared (10.000 for a 2 decimal result). Then it prints that last number.

for(;$a++<$z=$argv[1];)for(;$$a++<1e6;)$g++;for(;$b++<$g;$i=$x=0)for(;$i++<$b;)for($j=0;$j++<$b;)if(++$x>=$g)break 3;echo$b;

Run like this (-d added for aesthetic reasons only):

php -d error_reporting=32757 -r 'for(;$a++<$z=$argv[1];)for(;$$a++<1e6;)$g++;for(;$b++<$g;$i=$x=0)for(;$i++<$b;)for($j=0;$j++<$b;)if(++$x>=$g)break 3;echo"$b\n";' 2

Don't recommend trying this out with anything more than 3 decimals or a number above 10.

aross

Posted 2014-06-06T01:47:37.677

Reputation: 1 583

0

Haskell, 70 bytes

s i|r<-[1..i]=foldl1(.)[(+1)|j<-r,k<-r]
f i=[j-1|j<-[0..],s j 0>=i]!!1

f gives the integer square root by finding the largest number whose square is less than or equal to the input. The squaring function s i increments by one for every element of an (i,i) matrix. (Typed on phone so might have typos).

Michael Klein

Posted 2014-06-06T01:47:37.677

Reputation: 2 111