문제:
어떤 자연수 n이 있을 때, d(n)을 n의 각 자릿수 숫자들과 n 자신을 더한 숫자라고 정의하자.
예를 들어
d(91) = 9 + 1 + 91 = 101
이 때, n을 d(n)의 제네레이터(generator)라고 한다. 위의 예에서 91은 101의 제네레이터이다.
어떤 숫자들은 하나 이상의 제네레이터를 가지고 있는데, 101의 제네레이터는 91 뿐 아니라 100도 있다. 그런데 반대로, 제네레이터가 없는 숫자들도 있으며, 이런 숫자를 인도의 수학자 Kaprekar가 셀프 넘버(self-number)라 이름 붙였다. 예를 들어 1,3,5,7,9,20,31 은 셀프 넘버 들이다.
1 이상이고 5000 보다 작은 모든 셀프 넘버들의 합을 구하라.
출처: codingdojang.com/scode/365?answer_mode=hide
Idea:
1. generator, n은 항상 d(n)보다 작기 때문에, 1부터 5000까지의 모든 자연수를 generator n로 취급하여 5000개의 d(n)을 구한다.
2. d(n)을 구할 때, 각 자릿 수의 합은 (int -> string -> 여러개의 char -> 여러개의 int)의 과정을 거친 결과인 여러개의 int와 n 자신을 더하여 d(n)을 만든다.
3. 위에서 구한 d(n)을 HashSet set에 저장한다. <- d(n)은 중복된 수가 많아서 깔끔하게 정리하기 위함.
4. 1부터 5000까지의 모든 수를 가지고 있는 HashSet set_check를 만든다.
5. set_check 차집합 set을 하면 남은 수들이 1과 5000사이에 있는 self number가 된다.
Code:
import java.util.HashSet;
import java.util.Iterator;
public class SelfNumberFinder {
public static void main(String arg[]) {
int limit = 5000; // 1에서 5000사이의 self-number를 찾는 프로그램이다.
HashSet<Integer> set = new HashSet<Integer>();
HashSet<Integer> set_check = new HashSet<Integer>(limit); // 1부터 5000까지의 수를 저장할 set
for(int nat_num = 1; nat_num <= limit; nat_num++) {
//각 자릿수의 합을 구하는 첫번째 방법: string으로 바꾸고,
//str.charAt(int i)을 이용하여 i번째 인덱스의 char ch값을 받아서
//char값을 Character.getNumericValue(char ch)로 int 형으로 변환
int temp_int = 0;
String temp_str = String.valueOf(nat_num); // nat_num을 string으로 변환.
for(int i = 0; i < temp_str.length(); i++) {
char ch = temp_str.charAt(i); // i번째 string의 값을 추출해서 ch에 저장
temp_int += Character.getNumericValue(ch); // ch값을 int로 추출해서 temp_int에 더해서 저장.
}
set_check.add(nat_num); // 1부터 5000까지의 값을 hashset에 저장.
set.add(nat_num + temp_int); // HashSet set에 값 저장.
}
set_check.removeAll(set); // 차집합의 결과가 곧 1부터 5000까지의 자연수 중 self number
Iterator iter = set_check.iterator(); // Iterator iter선언.
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}
위 Idea의 2번 과정이 너무 복잡해서 더욱 간단한 코드로 다시 구현해보았다.
아래는 Idea의 2번 과정만 수정한 코드이다.
import java.util.HashSet;
import java.util.Iterator;
public class SelfNumberFinder {
public static void main(String arg[]) {
int limit = 5000; // 1에서 5000사이의 self-number를 찾는 프로그램이다.
HashSet<Integer> set = new HashSet<Integer>();
HashSet<Integer> set_check = new HashSet<Integer>(limit); // 1부터 5000까지의 수를 저장할 set
for(int nat_num = 1; nat_num <= limit; nat_num++) {
int num = nat_num;
int sum = 0;
while(num!=0) {
sum += num%10; //num을 10으로 나눈 값을 더해서 sum에 저장
num /= 10; //num은 10으로 나눈 몫으로 초기화.
}
set_check.add(nat_num); // 1부터 5000까지의 값을 hashset에 저장.
set.add(nat_num + sum); // HashSet set에 값 저장.
}
set_check.removeAll(set); // 차집합의 결과가 곧 1부터 5000까지의 자연수 중 self number
Iterator iter = set_check.iterator(); // Iterator iter선언.
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}
위의 코드에서 수정된 부분은 다음과 같다.
int num = nat_num;
int sum = 0;
while(num!=0) {
sum += num%10; //num을 10으로 나눈 값을 더해서 sum에 저장
num /= 10; //num은 10으로 나눈 몫으로 초기화.
}
위의 while문은 쓰임새가 많으니 외워두자.
실행결과는 다음과 같이 나온다.
'Java' 카테고리의 다른 글
[Java] Baekjoon_P11720 문자열의 각 자리 정수 합 구하기. (0) | 2020.12.20 |
---|---|
[Java] 1부터 10000까지의 자연수에서 8의 개수를 세는 연습문제. (0) | 2020.12.16 |
[Java] enum과 switch문 관련 예제 (0) | 2020.12.16 |
[Java 연습문제] String class의 method연습 (0) | 2020.12.10 |
[Java 연습문제] 중첩된 덧셈(for문과 static method 연습) (0) | 2020.12.10 |