44
\$\begingroup\$

Challenge

So, um, it seems that, while we have plenty of challenges that work with square numbers or numbers of other shapes, we don't have one that simply asks:

Given an integer n (where n>=0) as input return a truthy value if n is a perfect square or a falsey value if not.


Rules

  • You may take input by any reasonable, convenient means as long as it's permitted by standard I/O rules.
  • You need not handle inputs greater than what your chosen language can natively handle nor which would lead to floating point inaccuracies.
  • Output should be one of two consistent truthy/falsey values (e.g., true or false, 1 or 0) - truthy if the input is a perfect square, falsey if it's not.
  • This is so lowest byte count wins.

Test Cases

Input:  0
Output: true

Input:  1
Output: true

Input:  64
Output: true

Input:  88
Output: false

Input:  2147483647
Output: false
\$\endgroup\$
  • \$\begingroup\$ @Neil I realized my mistake. I retract that suggestion, and instead offer 18014398509481982 (2**54-2), which is representable with a double, and causes answers that use sqrt to fail. \$\endgroup\$ – Mego Jun 8 '17 at 12:24
  • \$\begingroup\$ @Mego I'm probably wrong or just misunderstanding what you're saying, but I'm sure 2**54-2 is still larger than a double can safely handle, at least in JavaScript 18014398509481982 > 9007199254740991 \$\endgroup\$ – Tom Jun 8 '17 at 12:32
  • \$\begingroup\$ @Mego I think the limiting value is 9007199515875288. It's not the square of 94906267, because that's not representable in a double, but if you take its square root, then you get that integer as the result. \$\endgroup\$ – Neil Jun 8 '17 at 12:33
  • \$\begingroup\$ @Tom Type 2**54-2 into a JS console, and compare what you get with 18014398509481982 (the exact value). JS outputs the exact value, therefore 2**54-2 is representable with a double. If that still doesn't convince you, take the binary data 0100001101001111111111111111111111111111111111111111111111111111, interpret it as a IEEE-754 double-precision float, and see what value you get. \$\endgroup\$ – Mego Jun 8 '17 at 12:41
  • 3
    \$\begingroup\$ Sorry, guys, stepped away for lunch and ... well, that escalated! And there I thought this would be a nice, simple challenge! Would adding a rule that you need not handle inputs that lead to floating point inaccuracies in your chosen language cover it? \$\endgroup\$ – Shaggy Jun 8 '17 at 13:17

66 Answers 66

2
\$\begingroup\$

PHP, 26 bytes

<?=(0^$q=sqrt($argn))==$q;

Try it online!

\$\endgroup\$
2
\$\begingroup\$

CJam, 12 bytes

{_),2f##)!!}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

APL, 5 bytes

⊢∊⍳×⍳

Explanation:

⊢           N
  ∊         in
    ⍳        numbers up to N
      ×     times
        ⍳    numbers up to N

Test:

      ((⊢∊⍳×⍳) ¨ X) ,[÷2] X←⍳25
1 0 0 1 0 0 0 0 1  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
\$\endgroup\$
  • \$\begingroup\$ Can you add a TIO (or equivalent)? \$\endgroup\$ – Shaggy Jun 8 '17 at 13:22
  • \$\begingroup\$ doesn't work for 0, but you could do ⊢∊0,⍳×⍳ and it's still the shortest APL answer \$\endgroup\$ – ngn Jun 15 '18 at 11:07
2
\$\begingroup\$

JavaScript on NodeJS & Chrome, 51 bytes

// OLD: t=n=>{i=Number.isSafeInteger;return i(n)&&i(n**.5)}

i=Number.isSafeInteger;t=n=>i(n)&&i(n**.5) 
// TestCases:
let l=console.log;l(`t(1): ${t(1)}; t(64): ${t(64)}; t(88): ${t(88)};`)

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG. You don't need to include the t= in your byte count nor is input validation required for this challenge. \$\endgroup\$ – Shaggy Jun 8 '17 at 14:00
  • \$\begingroup\$ Also works for Firefox \$\endgroup\$ – WORNG ALL Jul 3 '17 at 14:57
  • \$\begingroup\$ @rickhitchcock does have a point - input validation should not be required! Quote: "You need not handle inputs greater than what your chosen language can natively handle nor which would lead to floating point inaccuracies." \$\endgroup\$ – BogdanBiv Jul 10 '17 at 13:27
2
\$\begingroup\$

Python, 53 50 49 48 49 48 bytes

This should in theory work for an input of any size. Returns True if the given number is a square, False otherwise.

f=lambda n,x=0:x<=n if~-(x<=n!=x*x)else f(n,x+1)

Try it online!

Explanation:

f=                                                # assign a name so we can call it
  lambda n,x=0:                                   # counter variable x
               x<=n                               # counter bigger than input?
                    if~-(         )               # "negate" inner condition
                         x<=n                     # counter not bigger
                            n!=x*x                # and n not square of x
                                   else f(n,x+1)  # else recurse

The condition is just a de-Morgan'd if x>n or n==x**2, i.e. we return if the counter is bigger than the input, or we found a proof for squareness.

Saved 1 byte thanks to Gábor Fekete.

\$\endgroup\$
  • \$\begingroup\$ Your outputs are the wrong way 'round ;) \$\endgroup\$ – Shaggy Jun 8 '17 at 13:21
  • \$\begingroup\$ Technically, my output is "one of two consistent truthy/falsey values". But if you deem this invalid, I can correct it at the cost of one byte. \$\endgroup\$ – L3viathan Jun 8 '17 at 13:27
  • \$\begingroup\$ I'll edit the question to clarify, I see now that my phrasing in the rules was open to "interpretation", although it was clearer in the intro. \$\endgroup\$ – Shaggy Jun 8 '17 at 13:30
  • 1
    \$\begingroup\$ @Shaggy Yes, done. \$\endgroup\$ – L3viathan Jun 8 '17 at 13:38
  • 1
    \$\begingroup\$ Use x*x instead of x**2, saves 1 byte :) \$\endgroup\$ – Gábor Fekete Jun 8 '17 at 14:29
2
\$\begingroup\$

Actually, 6 bytes

;ur♂²c

Try it online!

-2 bytes from Erik the Outgolfer

Explanation:

;ur♂²c
;ur       range(n+1) ([0, n])
   ♂²     square each element
     c    does the list contain the input?

This takes a while for large inputs - TIO will timeout.

\$\endgroup\$
  • \$\begingroup\$ Can't you replace íub with c? \$\endgroup\$ – Erik the Outgolfer Jun 9 '17 at 15:09
  • \$\begingroup\$ @EriktheOutgolfer You're absolutely right I believe, and I have a lot of answers to update because I didn't think about that. \$\endgroup\$ – Mego Jun 10 '17 at 1:30
  • \$\begingroup\$ I actually tried to outgolf you, but then I thought the algorithm was way too similar to post, so I converted it to a golfing tip instead... \$\endgroup\$ – Erik the Outgolfer Jun 10 '17 at 10:09
2
\$\begingroup\$

C (gcc), 66 43 42 bytes

f(float n){return!(sqrt(n)-(int)sqrt(n));}

Try it online!

Thanks to TheLethalCoder for the tip!

@hvd Thanks for saving a byte!

\$\endgroup\$
  • \$\begingroup\$ Can you just do: bool f(float n){return !sqrt(n)-(int)sqrt(n)>0;} or similar? Been a while since I've used C. \$\endgroup\$ – TheLethalCoder Jun 8 '17 at 12:21
  • \$\begingroup\$ @TheLethalCoder yea absolutely man. :) i would have to incluede stdbool.h though, therefore int as return type would be shorter. \$\endgroup\$ – Abel Tom Jun 8 '17 at 12:26
  • \$\begingroup\$ There's no need for a space between return and !. \$\endgroup\$ – hvd Jun 11 '17 at 13:54
  • 1
    \$\begingroup\$ Suggest f(n) instead of f(float n) and (n=sqrt(n)) instead of (int)sqrt(n). \$\endgroup\$ – ceilingcat Nov 2 '17 at 4:33
2
\$\begingroup\$

MIPS, 112 bytes

main:li $v0,7
syscall
sqrt.d $f0,$f0
mfc1 $a0,$f0
li $v0,1
beqz $a0,t
li $a0,0
syscall
b e
t:li $a0,1
syscall
e:

Try it online!

Outputs 1 if the input is square, 0 if not.

Explanation

main:li $v0,7      #Start of program. Load service 7 (read input as float to $f0). 
                   #Input can be an integer, but MIPS will interpret it as a float.
syscall            #Execute.

sqrt.d  $f0,$f0    #Overwrite $f0 with its square root, stored as a double.
mfcl    $a0,$f0    #Move $f0 to $a0.
li      $v0,1      #Load service 1 (print int from $a0).
beqz    $a0,t      #Branch to label 't' if $a0 = 0. Otherwise continue.

#If input is non-square...
li      $a0,0      #Load 0 into $a0.
syscall            #Execute (print $a0).
b e                #Branch to label 'e'.

#If input is square...
t:li    $a0,1      #Start of label 't'. Load 1 into $a0.
syscall            #Execute (print $a0).

e:                 #Start of label 'e'. Used to avoid executing 't' when input isn't square.

A double in MIPS is 16 hexes. It shares its address with a float containing its low-order 8 hexes ($f0 in this case). The high-order hexes are stored in the next register ($f1), also as a float.

          float             double 
$f0     0000 0000     1111 1111 0000 0000
$f1     1111 1111

Taking the square root of a non-square number requires the entire double in order to be stored, meaning the high and low floats are populated. The square root of a square number only needs a few hexes from the double to be stored, and it is stored specifically in its high-order hexes. This means the low float is left at 0.

If the low float equals 0, the input is a square number.

\$\endgroup\$
2
\$\begingroup\$

Whitespace, 95 bytes

[S S S N
_Push_0][S N
S _Duplicate_top][T N
T   T   _Read_STDIN_as_integer][N
S S N
_Create_Label_LOOP][S N
S _Duplicate_top][S N
S _Duplicate_top][T S S N
_Multiply_top_two][S S S N
_Push_0][T  T   T   _Retrieve_input][S N
T   _Swap_top_two][T    S S T   _Subtract][S N
S _Duplicate_top][N
T   S S N
_If_0_jump_to_Label_TRUE][N
T   T   T   N
_If_negative_jump_to_Label_FALSE][S S S T   N
_Push_1][T  S S S _Add][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_TRUE][S S S T N
_Push_1][T  N
S T _Print_as_integer][N
N
N
_Stop_program][N
S S T   N
_Create_Label_FALSE][S S S N
_Push_0][T  N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Outputs 1/0 for truthy/falsey respectively. A few bytes could be saved if something like 00/0 for truthy/falsey is allowed instead.

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Read STDIN as integer, and store it in the heap
Integer i = 0
Start LOOP:
  Integer temp = i*i - input from heap
  If(temp == 0):
    Call function TRUE
  If(temp < 0):
    Call function FALSE
  i = i + 1
  Go to next iteration of LOOP

function TRUE:
  Print 1 as integer
  Stop program
function FALSE:
  Print 0 as integer
  (implicitly stop the program with an error)

Here a port of this approach in Java:

int func(int input){
  for(int i=0; /*infinite loop*/; i++){
    int m = input - i*i;
    if(m==0) return 1;
    if(m<1) return 0;
  }
}

Try it online.

\$\endgroup\$
1
\$\begingroup\$

Pyth, 5 bytes

/^R2h

Try it here!

\$\endgroup\$
  • \$\begingroup\$ An alternative 5-byte solution that doesn't work for larger numbers (e.g. 2**127 - 1) would be sI@Q2, but I have to admit that I am quite fond of your right map answer. \$\endgroup\$ – notjagan Jun 8 '17 at 15:19
1
\$\begingroup\$

QBIC, 16 18 bytes

[:|~b/a=a|_Xq}?b=0

Added two bytes for 0-case

This runs through i = 1 ... n to see if n / i == i. Prints 1 if such an i is found, prints -1 for N=0 and 0 in all other cases. Both 1 and -1 are considered truthy in QBasic (-1 being the actual value for true, but IF (n) only is false on n=0).

\$\endgroup\$
  • \$\begingroup\$ Can you add a TIO (or equivalent)? \$\endgroup\$ – Shaggy Jun 8 '17 at 13:21
  • \$\begingroup\$ @Shaggy unfortunately not. My attempts to have QBasic / QBIC / DosBox run on a webpage have been unfruitful, to put it mildly... I've considered running it from CGI, but QBasic is just too powerful to do that, that's asking for exploits... I'm open to suggestions. \$\endgroup\$ – steenbergh Jun 8 '17 at 13:23
  • \$\begingroup\$ I just wanted to check if it returns true for 0. \$\endgroup\$ – Shaggy Jun 8 '17 at 13:25
  • \$\begingroup\$ @Shaggy it would print 0 for N=0. It never enters the FOR loop and jumps straight to the last statement. I'll fix that \$\endgroup\$ – steenbergh Jun 8 '17 at 13:28
1
\$\begingroup\$

C, 33 bytes

#define f(x)sqrt(x)==(int)sqrt(x)

Takes an integer x. Checks if the square root of x is the square root of x rounded to an integer.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pari/GP, 8 bytes

issquare

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pyke, 3 bytes

,$P

Try it here!

,   -   sqrt(input)
 $  -  float(^)
  P - is_int(^)

This could be two bytes (and is in older versions) if Pyke didn't helpfully automatically cast the results of sqrt to an integer if it's a square number.

\$\endgroup\$
1
\$\begingroup\$

Charcoal, 8 bytes

¬﹪XN·⁵¦¹

Try it online!

Explanation

¬           Not
 ﹪      ¦¹ Modulo 1
   X  ·⁵   To the power of .5
     N     Next input as number, 
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 5 3 bytes

t.ï

Try it online!

Longer than @Erik's but just wanted to give it a shot.

Now shorter than Erik's but fails for large numbers...

Explanation

t            # square roots the input
 .ï          # checks if number on stack is an int
             # implicit output of result (0 or 1)
\$\endgroup\$
1
\$\begingroup\$

Python 3, 39 38 Bytes

lambda n:n in(i*i for i in range(n+1))

@mathmandan I had the same idea, and this implementation is 1 byte shorter. I wanted to comment on your post but do not yet have 50 reputation. I hope you see this!

This is just brute force, and I did not get it to complete 2147483647 in a reasonable amount of time.

Thanks @DJMcMayhem for suggesting i remove the space after in

Try it Online

\$\endgroup\$
  • \$\begingroup\$ Welcome to the site! Just FYI, you could remove a space after in \$\endgroup\$ – DJMcMayhem Jun 9 '17 at 20:04
  • \$\begingroup\$ Could you add a TIO or equivalent, please? \$\endgroup\$ – Shaggy Jul 3 '17 at 16:11
1
\$\begingroup\$

Excel, 18 16 bytes

=MOD(A1^0.5,1)=0
\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 30 bytes

(defun g(x)(=(mod(sqrt x)1)0))

Try it online!

or, with the same length,

(defun g(x)(integerp(sqrt x)))
\$\endgroup\$
1
\$\begingroup\$

><>, 22+3 = 25 bytes

01-\:*=n;
(?!\1+::*{:}

Try it online!

Input is expected on the stack at program start, so +3 bytes for the -v flag.

\$\endgroup\$
1
\$\begingroup\$

tinylisp, 67 bytes

(load library
(d S(q((n)(contains?(map(q((x)(* x x)))(c 0(1to n)))n

Try it online!

Generates a list of numbers from 0 through n, maps a lambda function that squares each one, and checks if n is in the resulting list of squares. Wildly inefficient, of course.


Here's a 77-byte solution that doesn't use the library and runs an order of magnitude faster:

(d _(q((x n s)(i(e n s)1(i(l n s)0(_(a x 1)n(a s(a x(a x 1
(d S(q((n)(_ 0 n 0

Try it online!

This one uses a helper function _ which tracks a counter x and its square s. At each level of recursion, we return success if s equals n and failure if s is greater than n; otherwise, if s is still less than n, we recurse, incrementing x and calculating the next s by the formula (x+1)^2 = x^2 + x + x + 1.

\$\endgroup\$
1
\$\begingroup\$

Julia 0.6, 12 bytes

n->√n%1==0

Try it online!

Pretty straightforward, having the Unicode for square-root saves a few bytes.

\$\endgroup\$
1
\$\begingroup\$

Japt -¡E, 2 bytes

¬d

Run it online

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 26 bytes

!([math]::Sqrt("$args")%1)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 27 25 24 bytes

saved bytes by simplifying order of operation and comparing roots instead of squared value

lambda n:n**.5//1==n**.5

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Hello and welcome to PPCG. I think you should specify that you are using Python 3. Furthermore, is %1==0 not shorter and accomplishes the same? \$\endgroup\$ – Jonathan Frech Mar 3 at 13:52
  • \$\begingroup\$ @JonathanFrech This works in 2 and 3. And yes, %1==0 is shorter and wins. Is there an easy way to filter past answers by language of implementation so I can quickly see what other users have already submitted? \$\endgroup\$ – SmileAndNod Mar 3 at 14:11
  • 1
    \$\begingroup\$ It only works in some newer Python 2 versions. \$\endgroup\$ – Jonathan Frech Mar 3 at 14:16
  • \$\begingroup\$ @JonathanFrech Ah. I don't have access to old versions of python 2. Any site like TIO that tests all versions? \$\endgroup\$ – SmileAndNod Mar 3 at 14:19
  • \$\begingroup\$ Explicit untrue division was introduced in Python 2.2; no, unfortunately I do not know of any online Python version history interpreter site. \$\endgroup\$ – Jonathan Frech Mar 3 at 14:54
1
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 61 bytes

	N =INPUT
T	OUTPUT =EQ(X * X,N) 1
	X =LT(X,N) X + 1	:S(T)
END

Try it online!

Increment X until either X ^ 2 is equal to N in which case the program outputs 1 or until X > N in which case the program outputs nothing.

\$\endgroup\$
1
\$\begingroup\$

brainfuck, 42 bytes

->>,[[-<<<+>>>]<<++[[-<]<+>>>]<<<[<]>>>]<.

Try it online!

Outputs the NUL byte for square numbers and SOH for non-squares. Uses the property that square numbers are the cumulative sum of odd numbers, i.e. 1, 1+3, 1+3+5 etc.

There might be a better way of arranging the cells so as to reduce the number of pointer movements and save bytes.

\$\endgroup\$
  • \$\begingroup\$ Just tested this quickly on my phone and it seems to be giving different outputs for inputs of 1 & 64. \$\endgroup\$ – Shaggy Aug 27 at 16:12
  • \$\begingroup\$ @Shaggy On TIO it is using input as a character code, so 1 (49) will be square but 64 (54) won't be. @ and SOH both output the NUL byte for me. You can use an interpreter like copy.sh to test actual numbers more easily \$\endgroup\$ – Jo King Aug 27 at 21:11
  • \$\begingroup\$ You're not taking input as a number. Look at @Shaggy s comment on my answer. \$\endgroup\$ – Krzysztof Szewczyk Aug 28 at 12:34
  • \$\begingroup\$ I'm using the interpreter from copy.sh which does allow input as a number. I could have sworn there was an answer under standard IO that allowed numerical input as byte code, but I can't find it. I guess I'll add it and see if it passes community consensus \$\endgroup\$ – Jo King Aug 28 at 12:42
  • \$\begingroup\$ Ah, here it is. I wonder why it isn't under standard IO \$\endgroup\$ – Jo King Aug 28 at 12:43
1
\$\begingroup\$

Brain-Flak, 92 bytes

(({})){{}([(({}[({})({}())])[(())])](<>)){({}())<>}{}{((<{}>))<>{}}{}<>{}}{}({()(<{}>)}{}<>)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

k4, 12 9 bytes

 x=_x:sqrt

with num(s) to be checked passed right-side, e.g.

 x=_x:sqrt 36 35 25
101b

get square root and check if the it is equal to the square root cast to int. if not a square number, the square root will have a decimal place and the cast will cut the decimal off

edit: -3 thanks to ngn :)


K (oK), 8 bytes

x=`i$x:%

Try it online!

Same logic but in oK, an implementation of k6 (no online k4 interpreter that i'm aware of). Test like:

 x=`i$x:% 16 24 81
1 0 1
\$\endgroup\$
  • \$\begingroup\$ Could you add a TIO (or equivalent)? From your explanation, it sounds like you may have posted this to the wrong challenge. \$\endgroup\$ – Shaggy Aug 27 at 9:01
  • \$\begingroup\$ @Shaggy, apologies... i did. deleting \$\endgroup\$ – scrawl Aug 27 at 9:03
  • \$\begingroup\$ @Shaggy corrected \$\endgroup\$ – scrawl Aug 27 at 9:17
  • \$\begingroup\$ Thanks. Could you add a link to somewhere we can test it, though? \$\endgroup\$ – Shaggy Aug 27 at 10:00
  • \$\begingroup\$ @Shaggy i have added a solution in oK which can be tested at TIO! \$\endgroup\$ – scrawl Aug 27 at 13:52
0
\$\begingroup\$

J, 8 bytes

(=~<.)%:

Explanation:

  • %: square root
  • =~ is the argument equal to itself
  • <. floor of
  • =~<. a J hook, which modifies the right argument by applying <.
  • so, "is the floor of the square root equal to itself?"

Note: If we want to save the above to a variable as a verb, we must do, eg:

issq=.(=~<.)@%:
\$\endgroup\$
  • \$\begingroup\$ Could you add a TIO (or equivalent) to this, please? \$\endgroup\$ – Shaggy Jun 9 '17 at 8:19
  • \$\begingroup\$ I tried it, but it's not producing any output. Not sure if the J interpreter is down or if I'm missing something, but if you paste the following test into jconsole: (=~<.)%: 1 4 9 16 ,: 2 3 7 21 it will return a table with a row of 1s on top of a row of 0s, as expected. I tried putting the same into the "Code" section of TIO and then hitting run, but I get no output. \$\endgroup\$ – Jonah Jun 9 '17 at 18:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.