▶ 문제
https://www.acmicpc.net/problem/4673
4673번: 셀프 넘버
셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다. 양의 정수 n이 주어졌을 때,
www.acmicpc.net


▶ 설명
셀프 넘버가 아닌 수를 1부터 10000까지의 범위 안에서 출력하는 문제이다.
셀프넘버인 수를 먼저 찾아내서 그 수를 boolean 배열의 index로 연결시켜 true가 되도록 한 후,
그 배열에서 false 인 값을 가진 index 를 반환하여 출력하도록 하였다.
함수 카테고리에 있는 문제인 만큼 1부터 차례대로 d(n)을 반복하여 구하는 연산을 메소드로 만들었다.
▶ 문제 풀이
🌱 풀이.
public class Main {
static final int SCOPE = 10000;
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
boolean check[] = new boolean[SCOPE + 1];
for (int i = 1; i < SCOPE; i++) {
int n = d(i);
if (n <= SCOPE) {
check[n] = true;
}
}
for (int i = 1; i < SCOPE; i++) {
if (!check[i]) {
sb.append(i).append("\n");
}
}
System.out.println(sb);
}
private static int d(int n) {
int sum = n;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
}

변하지 않는 수이고, main 메소드와 더불어 d메소드에서도 쓰이므로 static final 키워드를 붙였다.

check[0] 은 무시하고 check[1]부터 check[10000]까지의 인덱스를 다룰 것이기 때문에 배열의 크기를 10000 + 1 하였다.
참고로 boolean 배열을 선언하면 동시에 false로 초기화 된다.

d(n) 값을 구한 뒤 이 값이 10000을 넘기지 않는다면 check 배열에 해당 index를 true 로 바꿔준다.
한 번만 check 원소에 true 값을 줄 수도 있겠지만, 문제에서 언급되었듯이 101가 91과 100을 2개의 생성자로 갖는 상황이라면 check[101]에 두 번 true 값을 주게 된다. 그러니까 어느 한 숫자가 여러개의 생성자를 가진다 하더라도 문제될 것이 없다.
그리고 n의 범위가 10000이 넘지 않을 때에만 값을 주도록 하는 조건을 추가한다.

check 배열에 값을 모두 주었다면 check[1]부터 끝 원소까지 false 인 index를 반환하여 출력하면 이 문제는 끝이난다.
▶ Log
이 문제를 풀면서 배열의 index에 관해 다시금 생각해 볼 수 있는 기회였다. 단순히 배열의 순서를 매겨주는 것이 아니라 때에 따라 index를 가지고 문제를 푸는 핵심 키가 될수 있다는 것이 조금 놀랍기도 했다.