Skip to main content
3 of 3
Golfed 8 bytes
DLosc
  • 39.2k
  • 5
  • 83
  • 141

tinylisp, 125 117 109 bytes

(d X(q((N I)(i(l N 1)N(X(s N I)(a I 2
(d S(q((I N)(i(a(X I 1)(X(s N I)1))(i(l N I)0(S(a I 1)N))1
(q((N)(S 0 N

The last line is an anonymous function that takes a number and returns 1 if it is the sum of two squares, 0 otherwise. Try it online!

Ungolfed/explanation

Look, ma, no library!

First, we define a helper function X that takes a number N and determines if it is (not) a square. A perfect square is the sum of consecutive odd numbers; therefore, subtracting the sum of the first several odd numbers from N (for an appropriate value of "several") will result in 0 if N is square. Thus, we recurse over increasingly large odd numbers (which we track as I) and subtract each one from N until N equals 0 (in which case N is square) or N is less than 0 (in which case N is not square):

(def not-square?        ; Define not-square?
  (lambda (N I)         ; as a function of two arguments:
    (if (less? N 1)     ;  If N is less than 1,
      N                 ;  return N (0 if square, negative if not square)
      (not-square?      ;  Else, recurse with these arguments:
        (sub2 N I)      ;   New N is previous N minus current odd number
        (add2 I 2)))))  ;   New I is the next odd number

Next, we'll define a function S that determines whether a number N is the sum of two squares. Our algorithm here is to recurse over integers I starting at 0: if I is not square, or N minus I is not square, try the next I until N is less than I, at which point N cannot be the sum of two squares. On the other hand, if I and N minus I are both square, then N is the sum of two squares.

(def sum-squares?           ; Define sum-squares?
  (lambda (I N)             ; as a function of two arguments:
    (if                     ;  If
      (add2                 ;   the sum of
        (not-square?        ;    0 if
          (sub2 N I)        ;    N minus I
          1)                ;    is square, < 0 otherwise
                            ;   and
        (not-square? I 1))  ;    0 if I is square, < 0 otherwise
                            ;  is truthy (nonzero), then:
      (if (less? N I)       ;   If N is less than I
        0                   ;   then return 0
        (sum-squares?       ;   Else, recurse with these arguments:
          (add2 I 1)        ;    New I is the next integer
          N))               ;    Same N
      1                     ;  Else (I and N minus I are both square), return 1

Finally, our submission is an anonymous function that takes N only and passes it to sum-squares? with a starting I of 0:

(lambda (N)
  (sum-squares? 0 N))
DLosc
  • 39.2k
  • 5
  • 83
  • 141