Integers: Recreation One, CodeWars Kata

Integers: Recreation One

1, 246, 2, 123, 3, 82, 6, 41 are the divisors of number 246. Squaring these divisors we get: 1, 60516, 4, 15129, 9, 6724, 36, 1681. The sum of these squares is 84100 which is 290 * 290.

Task

Find all integers between m and n (m and n integers such as 1 <= m <= n) such that the sum of their squared divisors is itself a square.

We will return an array of subarrays or of tuples (in C an array of Pair) or a string. The subarrays (or tuples or Pairs) will have two elements: first the number the squared divisors of which is a square and then the sum of the squared divisors.

Example:

list_squared(1, 250) --> [[1, 1], [42, 2500], [246, 84100]]
list_squared(42, 250) --> [[42, 2500], [246, 84100]]

The form of the examples may change according to the language, see "Sample Tests".

Note

In Fortran - as in any other language - the returned string is not permitted to contain any redundant trailing whitespace: you can use dynamically allocated character strings.

 

문제 해석

주어지는 입력값 m, n 사이의 수 중에서 약수의 제곱의 합이 어떤 수의 거듭제곱인 수를 모두 찾는 문제입니다. 예제의 246은 약수의 거듭제곱의 합이 84100이고 이것은 290*290입니다. 우리는 이런 수들을 모두 찾아서 해당하는 숫자와 거듭제곱의 합을 쌍으로 리턴해주어야 합니다.

입력값

  • long m, n: 숫자를 찾을 범위

출력값

  • String result: [[숫자, 거듭제곱의 합]...] 형태로 결과를 출력

 

My Solution

m부터 n까지 루프를 돌면서 약수를 찾아 ArrayList에 담았습니다. 그리고 Stream을 이용해서 먼저 map(item -> item * item) 거듭제곱을 하고, reduce((a, b) -> a + b)로 거듭제곱의 합을 구했습니다. 그다음 Math.sqrt()를 이용해서 거듭제곱인지 확인했습니다. 결과 출력은 Arrays.deepToString()을 활용했습니다.

솔루션 코드

테스트 코드

package com.codewars;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.LongStream;

public class IntegersRecreationOne {
    public static String listSquared(long m, long n) {
        ArrayList<Long[]> listSquare = new ArrayList<Long[]>();
        for (long N = m; N <= n; N++) {
            ArrayList<Long> list = new ArrayList<Long>();
            for (long div = 1; div <= N; div++) {
                if (N % div == 0) {
                    if (!list.contains(div))
                        list.add(div);
                }
            }
            if (!list.isEmpty()) {
                long multi = list.stream().map(item -> item * item).reduce((a, b) -> a + b).get();
                if ((long) Math.sqrt(multi) * (long) Math.sqrt(multi) == multi) {
                    listSquare.add(new Long[] { N, multi });
                }
            }

        }

        return Arrays.deepToString(listSquare.toArray());
    }
}

 

Best Practice

BP1

Math.sqrt() API를 적극 활용한 답안입니다. 결과를 String으로 조립해 나가는 게 흥미롭네요.

class SumSquaredDivisorsBP {

    public static String listSquared(long m, long n) {
        // your code
        String result = "[";
        for (long i = m; i <= n; i++) {
            if (Math.round(Math.sqrt(sumOfSquareDivisors(i))) == Math.sqrt(sumOfSquareDivisors(i))) {
                result += "[" + i + ", " + sumOfSquareDivisors(i) + "], ";
            }
        }
        return result.length() > 1 ? result.substring(0, result.length() - 2) + "]" : "[]";
    }

    public static long sumOfSquareDivisors(long n) {
        return LongStream.range(1, n + 1).filter(i -> n % i == 0).map(i -> i * i).sum();
    }
}

 

BP2

루프를 사용하는 대신 LongStream을 활용한 게 눈여겨 볼만합니다.  

class SumSquaredDivisorsBP2 {

    public static String listSquared(long m, long n) {
        ArrayList<String> strings = new ArrayList<>();
        LongStream.rangeClosed(m, n).forEach(current -> {
            long sum = LongStream.rangeClosed(1, current).filter(i -> current % i == 0).map(i -> i * i).sum();
            if (Math.sqrt(sum) % 1 == 0)
                strings.add(String.format("[%d, %d]", current, sum));
        });
        return String.valueOf(strings);
    }
}

 

728x90
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기