52
\$\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\$
10
  • \$\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\$
    – user45941
    Jun 8, 2017 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, 2017 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, 2017 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\$
    – user45941
    Jun 8, 2017 at 12:41
  • 4
    \$\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, 2017 at 13:17

81 Answers 81

3
\$\begingroup\$

Ohm, 2 bytes

Ʋ

Uses CP-437 encoding.

Explanation

Implicit Input -> Perfect square built-in -> Implicit Output...

\$\endgroup\$
0
3
\$\begingroup\$

Java 8, 20 bytes

n->Math.sqrt(n)%1==0

Input is an int.

Try it here.

\$\endgroup\$
4
  • \$\begingroup\$ Not debatable: the question explicitly says "Given an integer n (where n>=0)". The shortest answer is the best. Edit: won't +1 until the shortest answer isn't the first :p \$\endgroup\$ Jun 8, 2017 at 13:03
  • \$\begingroup\$ @OlivierGrégoire Hmm, that's a good way to look at it. But you still wouldn't know whether it's an int, long, short. And with questions where they ask for an integer but the input format is flexible, I sometimes use a String input to save some bytes. Personally I think using n-> is fine, and you should just state what the type is, but apparently not everyone agrees with this. On the other hand, coming from a Java 7 answer history, going from int c(int n){return ...;} to (int n)->... makes more sense than n->... (even though I personally prefer the second since shorter of course). \$\endgroup\$ Jun 8, 2017 at 13:10
  • 2
    \$\begingroup\$ @OlivierGrégoire Ok, I've changed it. After reading the discussion in this answer, I came to the conclusion that stating the input is an integer in Java, is no difference than stating the input is a list of two Strings in CJam or a cell array of strings in MATL. \$\endgroup\$ Jun 9, 2017 at 8:05
  • \$\begingroup\$ nvm, I'm stupid :P \$\endgroup\$
    – 0xff
    Oct 16, 2021 at 12:55
3
\$\begingroup\$

Add++, 24 13 11 bytes

+?
S
%1
N
O

Try it online!

I removed the clunky function at the top and rewrote it into the body of the question to remove 11 bytes.

As the first section is already explained below, let's only find out how the new part works

S   Square root
%1  Modulo by 1. Produced 0 for integers and a decimal for floats
N   Logical NOT

Old version, 24 bytes

D,i,@,1@%!
+?
^.5
$i,x
O

Try it online!

The function at the top (D,i,@,1@%!) is the main part of the program, so let's go into more detail.

D,     Create a function...
  i,   ...called i...
  @,   ...that takes 1 argument (for this example, let's say 3.162 (root 10))
    1  push 1 to the stack; STACK = [1, 3.162]
    @  reverse the stack;   STACK = [3.162, 1]
    %  modulo the stack;    STACK = [0.162]
    !  logical NOT;         STACK = [False]

+?     Add the input to accumulator (x)
^.5    Square root (exponent by 0.5)
$i,x   Apply function i to x
O      Output the result
\$\endgroup\$
3
\$\begingroup\$

Python 3, 28 27 25 bytes

  • Thanks to @mdahmoune for 1 byte: compare int of root squared with original
  • 2 bytes saved: lambda shortened
lambda x:int(x**.5)**2==x

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ what about f=lambda x:int(x**.5)**2==x 27bytes \$\endgroup\$
    – mdahmoune
    Jul 3, 2017 at 15:30
2
\$\begingroup\$

CJam, 12 bytes

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

Try it online!

\$\endgroup\$
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\$
3
  • \$\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, 2017 at 14:00
  • \$\begingroup\$ Also works for Firefox \$\endgroup\$
    – WORNG ALL
    Jul 3, 2017 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, 2017 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\$
7
  • \$\begingroup\$ Your outputs are the wrong way 'round ;) \$\endgroup\$
    – Shaggy
    Jun 8, 2017 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, 2017 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, 2017 at 13:30
  • 1
    \$\begingroup\$ @Shaggy Yes, done. \$\endgroup\$
    – L3viathan
    Jun 8, 2017 at 13:38
  • 1
    \$\begingroup\$ Use x*x instead of x**2, saves 1 byte :) \$\endgroup\$ Jun 8, 2017 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\$
3
  • \$\begingroup\$ Can't you replace íub with c? \$\endgroup\$ Jun 9, 2017 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\$
    – user45941
    Jun 10, 2017 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\$ Jun 10, 2017 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\$
4
  • \$\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\$ Jun 8, 2017 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, 2017 at 12:26
  • \$\begingroup\$ There's no need for a space between return and !. \$\endgroup\$
    – hvd
    Jun 11, 2017 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, 2017 at 4:33
2
\$\begingroup\$

PowerShell, 26 bytes

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

Try it online!

\$\endgroup\$
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
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\$
2
\$\begingroup\$

Rockstar, 55 bytes

First time posting a solution to one of my own challenges, if you'll forgive me the indulgence.

Outputs 1 for truthy or nothing for falsey.

listen to N
X's0
while N-X
let X be+1
if X*X is N
say 1

Try it here (Code will need to be pasted in)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ For a Rockstar answer, anything can be forgiven. \$\endgroup\$
    – user
    Mar 22, 2021 at 0:57
2
\$\begingroup\$

V (vim), 34 bytes

C<C-r>=sqrt(<C-r>")
<esc>:s/.\+\.0\n
:s/.\+/1

Try it online!

Returns empty string for a square, 1 for non-square.

Explanation

C<C-r>=sqrt(<C-r>")
C                   cut the input line, enter insert mode
 <C-r>=             evaluate the following math command:
       sqrt(      ) square root of
            <C-r>"  cut input line in register "

<esc>:s/.\+\.0\n/
<esc>               exit insert mode
     :s/.\+\.0\n/   remove instance of <digits>.0 
                    this removes a perfect square root.

:s/.\+/1            replace any other non-newline chars left with
                    a single 1.
\$\endgroup\$
2
\$\begingroup\$

JavaScript, 44 bytes

n=>{for(i=0n;i<=n;){if(i++**2n==n)return 1}}

Obligatory bigger but BigInt answer.

Returns 1 if a square, or undefined when not a square.

+4 bytes if you want to actually get your answer today:

n=>{for(i=0n;i**2n<=n;){if(i++**2n==n)return 1}}
\$\endgroup\$
2
  • \$\begingroup\$ @emanresuA could you elaborate on how the first one would be but not the second? because the only thing I can think of is i not fitting in your memory at some point, but that can happen for both \$\endgroup\$
    – Leaf
    Mar 7 at 9:49
  • 1
    \$\begingroup\$ Ah, never mind, I misread it as not having a condition on the loop. Sorry \$\endgroup\$
    – emanresu A
    Mar 7 at 18:36
2
\$\begingroup\$

Knight, 32 33 32 30 bytes

;=i+1=xP;W!>0=i-i 1|-^i 2xQ1Q0

Try it online!

Takes input from standard in, outputs by error code (1 if input is square, 0 otherwise).

Expanded code:

;=i +1 (=x PROMPT)
;WHILE !> 0(=i -i 1)
  | (-(^i 2) x)
    QUIT 1
QUIT 0

+1 bytes from @Jonah because I somehow didn't notice this failed on input 1
-2 bytes from @Jonah by using short circuit evaluation of | instead of IF

\$\endgroup\$
4
  • \$\begingroup\$ I think Q?0x can just be Q0 because if you get there we know it's not square. \$\endgroup\$
    – Jonah
    Aug 6, 2022 at 20:29
  • 1
    \$\begingroup\$ @Jonah if the input is 0, then the while loop will never run, so it will go straight to the "false" case -- I need to check for that. \$\endgroup\$ Aug 6, 2022 at 20:32
  • \$\begingroup\$ I see. Looks like current answer fails for 1. \$\endgroup\$
    – Jonah
    Aug 6, 2022 at 20:36
  • 1
    \$\begingroup\$ -2 with ;=i+1=xP;W!>0=i-i 1|-^i 2xQ1Q0 \$\endgroup\$
    – Jonah
    Aug 6, 2022 at 21:14
1
\$\begingroup\$

Pyth, 5 bytes

/^R2h

Try it here!

\$\endgroup\$
1
  • \$\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, 2017 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\$
4
  • \$\begingroup\$ Can you add a TIO (or equivalent)? \$\endgroup\$
    – Shaggy
    Jun 8, 2017 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, 2017 at 13:23
  • \$\begingroup\$ I just wanted to check if it returns true for 0. \$\endgroup\$
    – Shaggy
    Jun 8, 2017 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, 2017 at 13:28
1
\$\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\$
2
  • \$\begingroup\$ Could you add a TIO (or equivalent) to this, please? \$\endgroup\$
    – Shaggy
    Jun 9, 2017 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, 2017 at 18:24
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\$
2
  • \$\begingroup\$ Welcome to the site! Just FYI, you could remove a space after in \$\endgroup\$
    – DJMcMayhem
    Jun 9, 2017 at 20:04
  • \$\begingroup\$ Could you add a TIO or equivalent, please? \$\endgroup\$
    – Shaggy
    Jul 3, 2017 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\$

Ruby, 16 bytes

->n{n**0.5%1==0}

Trivial solution.

\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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