티스토리 뷰
2. 셀프 넘버
문제
셀프 넘버
문제
셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다.
양의 정수 n이 주어졌을 때, 이 수를 시작해서 n, d(n), d(d(n)), d(d(d(n))), ...과 같은 무한 수열을 만들 수 있다.
예를 들어, 33으로 시작한다면 다음 수는 33 + 3 + 3 = 39이고, 그 다음 수는 39 + 3 + 9 = 51, 다음 수는 51 + 5 + 1 = 57이다. 이런식으로 다음과 같은 수열을 만들 수 있다.
33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, ...
n을 d(n)의 생성자라고 한다. 위의 수열에서 33은 39의 생성자이고, 39는 51의 생성자, 51은 57의 생성자이다. 생성자가 한 개보다 많은 경우도 있다. 예를 들어, 101은 생성자가 2개(91과 100) 있다.
생성자가 없는 숫자를 셀프 넘버라고 한다. 100보다 작은 셀프 넘버는 총 13개가 있다. 1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97
10000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 출력하는 프로그램을 작성하시오.
입력
입력은 없다.
출력
10,000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 증가하는 순서로 출력한다.
예제 입력 1
예제 출력 1
1
3
5
7
9
20
31
42
53
64
|
| <-- a lot more numbers
|
9903
9914
9925
9927
9938
9949
9960
9971
9982
9993
해답
function d(n) {
let sum = n;
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
return sum;
}
const selfNum = new Array(10000);
selfNum.fill(true);
for (let i = 1; i <= 10000; i++) {
selfNum[d(i)] = false;
if (selfNum[i]) {
console.log(i);
}
}
풀이
function d(n) (생성자를 구하는 함수)
function d(n) {
let sum = n;
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
return sum;
}
일정한 범위 내에서 생성자가 없는 숫자인 셀프 넘버를 구하기 위해서는 전체 범위에서 생성자를 빼주면 됩니다.
우선 생성자를 구하는 함수가 필요합니다.
sum (생성자)
let sum = n;
sum
이라는 변수에 매개변수 양의 정수를 뜻하는 n
을 할당합니다.
만약 n
이 123
인 경우 sum
은 123
이 됩니다.
while (생성자를 만드는 과정)
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
while (n > 0) {}
while문을 활용해 n > 0
일 경우에만 진행을 하도록 합니다.
더하기 할당 (sum에 n의 나머지 값 더하기)
while (n > 0) {
sum += n % 10;
}
더하기 할당을 통해 n
값을 할당한 변수 sum
에 n
의 10으로 나눈 나머지 즉 일의 자리 수를 더하여 줍니다.
예를 들어 숫자 123
일 경우 3
을 더하여 주는 것입니다.
Math.floor() (소수점 밑 버리기)
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
n
을 10
으로 나누면 소수점을 가진 실수가 되는데 Math.floor()
함수를 통해 정수화 해줍니다. 그리고 그 값을 n
에 할당합니다.
예를 들어 123
의 경우 n / 10
을 하면 12.3
이 되는데 Math.floor()
을 통해 12
가 됩니다.
위와 같은 과정을 while (n > 0) {}
즉 n
이 0
보다 큰 경우 반복하게 되어 두 자리 수든 세 자리 수든 모든 자리수를 더한 값을 구할 수 있습니다.
return (생성자 sum 반환하기)
function d(n) {
let sum = n;
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
return sum;
}
console.log(d(123)); // 129
return
명령문을 통해 함수 실행을 종료하고 sum
값을 반환합니다. 즉 n
의 생성자 혹은 생성자들을 반환하게 되는 것입니다.
selfNum (셀프 넘버를 가지는 배열)
const selfNum = new Array(10000);
selfNum.fill(true);
Array() 생성자 (배열 생성하기)
const selfNum = new Array(10000);
Array()
를 활용하여 10000
개의 요소를 가지는 빈 배열을 생성하여 변수 selfNum
에 할당합니다.
fill() (배열의 요소 모두 true)
selfNum.fill(true);
아직 셀프 넘버인지 생성자인지 추려내지 않았기 때문에 fill()
메서드를 활용하여 모두 true
로 채웁니다.
for (selfNum 배열의 요소 추려내기)
for (let i = 1; i <= 10000; i++) {
selfNum[d(i)] = false;
if (selfNum[i]) {
console.log(i);
}
}
for (let i = 1; i <= 10000; i++) {}
selfNum
내의 요소들에 관한 반복문이므로 i
의 범위를 1
부터 10000
까지로 합니다.
생성자인 경우 요소 false로
for (let i = 1; i <= 10000; i++) {
selfNum[d(i)] = false;
}
d(i)
값과 일치하는 배열 selfNum
의 요소인 경우 false
로 할당합니다.
위의 과정을 통해 생성자인 요소는 false
가 되는 것이고, 생성자가 아닌 셀프 넘버인 요소는 true
값을 가지게 됩니다.
if...else (selfNum의 요소가 true인 경우)
for (let i = 1; i <= 10000; i++) {
selfNum[d(i)] = false;
if (selfNum[i]) {
console.log(i);
}
}
if...else문에 의해 selfNum[i]
가 true
일 경우 셀프 넘버이므로 console.log()
메서드로 i
값을 출력해줍니다.
3. 한수
문제
한수
문제
어떤 양의 정수 X의 각 자리가 등차수열을 이룬다면, 그 수를 한수라고 한다. 등차수열은 연속된 두 개의 수의 차이가 일정한 수열을 말한다. N이 주어졌을 때, 1보다 크거나 같고, N보다 작거나 같은 한수의 개수를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 1,000보다 작거나 같은 자연수 N이 주어진다.
출력
첫째 줄에 1보다 크거나 같고, N보다 작거나 같은 한수의 개수를 출력한다.
예제 입력 1
110
예제 출력 1
99
예제 입력 2
1
예제 출력 2
1
예제 입력 3
210
예제 출력 3
105
예제 입력 4
1000
예제 출력 4
144
예제 입력 5
500
예제 출력 5
119
해답
const fs = require("fs");
const inputData = +fs.readFileSync(
process.platform === "linux" ? "/dev/stdin" : "../../../../index.txt"
);
function arithmeticalSequence(n) {
if (n < 100) {
return true;
} else if (n < 1000) {
const number = n % 10;
const tens = Math.floor(n / 10) % 10;
const hundreds = Math.floor(n / 100);
if (number - tens === tens - hundreds) {
return true;
} else {
return false;
}
}
}
let count = 0;
for (let i = 1; i <= inputData; i++) {
if (arithmeticalSequence(i)) {
count++;
}
}
console.log(count);
풀이
inputData (입력값)
readFileSync() (파일 읽어오기)
const fs = require("fs");
const inputData = fs.readFileSync(
process.platform === "linux" ? "/dev/stdin" : "../../../../index.txt"
);
console.log(inputData); // <Buffer 31 30 30 30>
백준에서 추천하는 방식은 node.js에서 fs 모듈의 readFileSync()
를 이용하는 것입니다.
process.platform (작동 시스템 구별)
process.platform === "linux" ? "/dev/stdin" : "../../../../index.txt";
process.platform
이 "linux"
인 경우 경로를 "/dev/stdin"
으로 향하게 하고 그것이 아니면 사용자가 지정한 파일을 향하게 합니다.
+ (숫자형으로 변환)
const inputData = +fs.readFileSync(
process.platform === "linux" ? "/dev/stdin" : "../../../../index.txt"
);
console.log(inputData); // 1000
Buffer 형식으로 출력된 inputData
값을 숫자형으로 변환시킵니다.
arithmeticalSequence(n) (한수를 구하는 함수)
function arithmeticalSequence(n) {
if (n < 100) {
return true;
} else if (n < 1000) {
const number = n % 10;
const tens = Math.floor(n / 10) % 10;
const hundreds = Math.floor(n / 100);
if (number - tens === tens - hundreds) {
return true;
} else {
return false;
}
}
}
일정한 범위 내에서 한수의 개수를 출력을 해야합니다. 우선 특정한 수가 한수 즉 등차수열인지 아닌지를 가려내는 함수를 생성합니다.
if...else (범위마다 한수 추려내기)
if (n < 100) {
return true;
} else if (n < 1000) {
const number = n % 10;
const tens = Math.floor(n / 10) % 10;
const hundreds = Math.floor(n / 100);
if (number - tens === tens - hundreds) {
return true;
} else {
return false;
}
}
1000
보다 작거나 같은 자연수에 중에 한수를 찾아내는 것이기 때문에 if...else문을 활용하여 범위마다 구분합니다.
n < 100 (n이 100보다 작을 때)
if (n < 100) {
return true;
}
n
값이 100
보다 작을 경우 각 자리의 수가 모두 등차수열을 이루기 때문에 true
값을 반환합니다.
n < 1000 (n 100 이상이면서 1000보다 작을 경우)
if (n < 100) {
return true;
} else if (n < 1000) {
const number = n % 10;
const tens = Math.floor(n / 10) % 10;
const hundreds = Math.floor(n / 100);
if (number - tens === tens - hundreds) {
return true;
} else {
return false;
}
}
등차수열: 연속하는 두 항의 차이가 모두 일정한 수열
모두 true
인 100
미만의 경우를 제외하고 100
이상 1000
미만일 경우 즉 세 자리 수부터는 각 자리수가 등차수열이 될 수 없는 경우가 존재합니다.
그 존재를 가려내기 위해서 number
, tens
, hundreds
와 같이 각각 일의 자리 수, 십의 자리 수, 백의 자리 수를 의미하는 변수를 만들고,
등차수열의 특징에 따라 연속하는 두 항의 차이가 모두 일정해야하므로 number - tens === tens - hundreds
즉 일의 자리 수와 십의 자리 수의 차이가 십의 자리 수와 백의 자리 수의 차이와 같다면 true
를 반환하고, 그것이 아니라면 false
를 반환하게 합니다.
count (한수의 개수)
let count = 0;
한수의 개수를 의미하는 변수 count
를 선언하고 0
으로 초기화합니다.
for (inputData 값 이하의 수 한수 판단)
for (let i = 1; i <= inputData; i++) {
if (arithmeticalSequence(i)) {
count++;
}
}
for문을 통해 i
의 범위를 1
부터 주어진 자연수인 inputData
만큼으로 하여 이하의 식을 수행하게 합니다.
if...else (한수일 경우 count 값 증가)
if (arithmeticalSequence(i)) {
count++;
}
위에서 정의한 한수를 판별하는 함수인 arithmeticalSequence(i)
를 통해 i
의 값이 한수이면 즉 반환하는 값이 true
이면 증가 연산자를 통해 증가시킵니다.
console.log() (한수의 개수 출력하기)
console.log(count); // 144
console.log()
메서드를 활용해 한수의 개수를 의미하는 변수 count
를 출력합니다.
'Nodejs' 카테고리의 다른 글
[Nodejs][백준] 단계별로 풀어보기 - 4. 1차원 배열 (0) | 2022.07.27 |
---|---|
[Nodejs][백준] 단계별로 풀어보기 - 3. 반복문 (0) | 2022.07.22 |
[Nodejs][백준] 단계별로 풀어보기 - 2. 조건문 (0) | 2022.07.07 |
[Nodejs][백준] 단계별로 풀어보기 - 1. 입출력과 사칙연산 (0) | 2022.07.03 |
[Nodejs] nvm으로 Nodejs 버전 관리하기 (0) | 2021.09.29 |