The challenge

In this challenge, you will be given a number n (n > 0) and your task will be to return the smallest square number N (N > 0) such that n + N is also a perfect square. If there is no answer, return -1 (nil in Clojure, Nothing in Haskell, None in Rust).

1
2
3
4
5
6
7
solve 13 = 36
<em>; because 36 is the smallest perfect square that can be added to 13 to form a perfect square => 13 + 36 = 49</em>

solve 3 = 1 <em>; 3 + 1 = 4, a perfect square</em>
solve 12 = 4 <em>; 12 + 4 = 16, a perfect square</em>
solve 9 = 16 
solve 4 = nil

The solution in Golang

Option 1:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package solution
func Solve(n int) int {
  res := -1
  for i:= 1; i * i < n; i++ {
    if n % i == 0 && (n / i - i) % 2 == 0 {
      res = (n / i - i) *  (n / i - i) / 4
    }
  }
  return res
}

Option 2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package solution
import "math"
func Solve(n int) int {
  // n+a**2==b**2 => n=b2-a2=(a-b)(a+b) => b=(c+d)/2; a=d-b
  for i := int(math.Sqrt(float64(n))); i > 0; i-- {
    if n%i == 0 {
      c, d := i, n/i
      b := (c + d) / 2
      a := d - b
      if a > 0 && n+a*a == b*b { return a * a }
    }
  }
  return -1
}

Option 3:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package solution
import "math"
func Solve(n int) int {
  upperBound := n
  lowerBound := 1
  for  lowerBound <= upperBound {
    square := lowerBound*lowerBound
    numToCheck := math.Sqrt(float64(square + n))
    if math.Floor(numToCheck) == math.Ceil(numToCheck) {
      return square
    }
    lowerBound++ 
  }
  return -1
}

Test cases to validate our solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package solution_test
import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)
var _ = Describe("Example tests", func() {
  It("It should work for basic tests", func() {
    Expect(Solve(1)).To(Equal(-1))
    Expect(Solve(2)).To(Equal(-1))
    Expect(Solve(3)).To(Equal(1))
    Expect(Solve(4)).To(Equal(-1))  
    Expect(Solve(5)).To(Equal(4))
    Expect(Solve(7)).To(Equal(9))
    Expect(Solve(8)).To(Equal(1))
    Expect(Solve(9)).To(Equal(16))
    Expect(Solve(10)).To(Equal(-1))
    Expect(Solve(11)).To(Equal(25))
    Expect(Solve(13)).To(Equal(36))
    Expect(Solve(17)).To(Equal(64))
    Expect(Solve(88901)).To(Equal(5428900))
    Expect(Solve(290101)).To(Equal(429235524)) 
  })
})