Codewars 문제풀기 (04/06)
Find the next perfect square!
- long을 인수로 받는다.
- long은 어떤 자연수의 제곱이며 어떤 자연수+1의 제곱을 리턴한다.
- long이 어떤 자연수의 제곱이 아니라면 -1을 리턴한다.
- findNextSquare(121) –> 11의 제곱 –> 12의 제곱인 144 리턴
- findNextSquare(625) –> 25의 제곱 –> 26의 제곱인 676 리턴
- findNextSquare(114) –> 자연수의 제곱이 아님 –> -1 리턴
1. Test와 리팩토링
-
입력인수가 자연수의 제곱이 아닐경우 -1을 리턴한다.
-
테스트 코드
@Test public void testShouldReturnMinus1WhenInputIsNotPerfectSquare() { // Given: Set input integer not perfect square int given = 114; // When: Call findNextSquare method long actual = NumberFun.findNextSquare(given); // Then: Should return -1 assertEquals(-1, actual); }
-
실제 코드
public class NumberFun { public static long findNextSquare(long sq) { long temp = Math.sqrt(sq) != Math.ceil(Math.sqrt(sq)) ? -1 : 0; return temp; } }
-
인수 sq가 자연수의 제곱인 것을 어떻게 표현할까 생각해봤는데, 예를들어 sq가 144라면 sqrt(144)는 12를 반환할 것이고, 이 값을 올림해도 12일것이다. 반면 sq가 122라면 sqrt(122)는 11.xxx를 반환할 것이고, 이 값을 올림하면 12일것이다. 따라서
Math.sqrt(sq)!=Math.ceil(Math.sqrt(sq))
라면 -1을 반환하도록 구현했다.? -1 : 0;
구절에서 바로 다음 자연수의 제곱을 리턴할 수 있지만 TDD규칙상 테스트만 만족하면 되기때문에 굳이 구현하지 않았다.
-
리팩토링
public class NumberFun { public static long findNextSquare(long sq) { long sqrtOfSq = Math.sqrt(sq); return sqrtOfSq != Math.ceil(sqrtOfSq) ? -1 : 0; } }
Math.sqrt(sq)
를 지역변수로 추출했다.
-
-
입력 인수가 625라면 26의 제곱인 676을 리턴한다.
-
테스트 코드
@Test public void testShouldReturn676WhenInputIs625() { // Given: Set input integer 625(25 square) int given = 625; // When: Call findNextSquare method long actual = NumberFun.findNextSquare(given); // Then: Should return 676(26 square) assertEquals(676, actual); }
-
실제 코드
public class NumberFun { public static long findNextSquare(long sq) { double sqrtOfSq = Math.sqrt(sq); return sqrtOfSq == Math.ceil(sqrtOfSq) ? (long) Math.pow(sqrtOfSq + 1, 2) : -1; } }
- 이전 테스트 기준으로 작성한 코드에서 조금 바꿨다. sq의 제곱근과 sq의 제곱근을 올림한 값이 같다면 sq의 제곱근+1 을 제곱한 값을 리턴한다.
- 더 리팩토링할 요소가 없다고 판단해서 제출했다. (약 10분)
-
2. 답 비교, 느낀점
Best Practice 가장 많이 받은 코드
public class NumberFun {
public static long findNextSquare(long sq) {
long root = (long) Math.sqrt(sq);
return root * root == sq ? (root + 1) * (root + 1) : -1;
}
}
Math.sqrt(sq)
의 리턴값이 double형인데 long으로 형 변환을하면 소숫점들은 버리게된다(long root). 예를들어Math.sqrt(sq)
가 10.6681… 이라면, long 타입으로 변환하면 그냥 10이다.- 따라서 long타입으로 변환한 값(root)을 제곱한 값이 입력 인수와 같다면 그 값의 +1한 값의 제곱((root+1) * (root+1)) 이고 같지 않다면 -1을 리턴한다.
- 이 방법이 보기 더 직관성 있다. 그리고
Math.pow()
메서드를 사용하지 않았는데 더 직관적인것 같다.
댓글남기기