본문 바로가기
Algorithm/BOJ

함수 편 - Node.js로 [백준/BOJ] 단계별로 풀어보기를 풀어보다

by Muko 2020. 5. 17.

안녕하세요! muko 입니다.
이번 시간에는 백준BOJ의 함수 파트를 풀어보려고 합니다. 총 세문제가 있는데, 첫 번째 문제는 Node.js를 지원하지 않는 문제라서 나머지 두 문제에 대해서 풀이를 올리도록 하겠습니다!

BOJ 4373 - 셀프 넘버

# 문제

셀프 넘버는 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보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 출력하는 프로그램을 작성하시오.

# 풀이

이 문제는 두 가지 로직이 필요합니다. 첫 번째는 d(n)을 구하는 함수가 필요하고, 두 번째는 셀프넘버를 찾는 함수입니다.

첫 번째 d(n)을 구하는 함수의 경우에는 문제에서 제시하는 규칙을 그대로 반환하는 함수를 구현하면 됩니다. 이 때 자바스크립트는 정수를 문자열로 바꾼 뒤에 계산을 진행했을 때 훨씬 편하게 자리수를 나누어서 계산할 수 있습니다. 문자열을 한 문자 단위로 쪼개서 배열로 만든 다음, 배열을 순회하면서 자리 수 들을 더해가는 형식으로 구현하면 됩니다. 아래 코드에서는 const d = n => {...} 부분입니다.

두 번째 셀프넘버를 찾는 함수는 1부터 1만까지 탐색하면서 현재 숫자가 생성자가 있는지 없는지를 체크한 뒤, 없을 경우 정답으로 출력하는 로직을 구현하면 됩니다. 저는 생성자가 있는지 여부를 확인하기 위해서 flags라는 변수를 따로 만들었습니다. 처음에는 모두 false로 초기화 되어있는 상태에서 생성자가 되는 부분을 true로 만든 뒤, 나중에 탐색할 때 false인 부분만 탐색하는 식으로 코드를 작성하시면 됩니다.


// 입출력에 사용할 rl을 받아오는 함수
const getRl = () => {
  const readline = require('readline');
  return readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
}
const rl = getRl();

const d = n => {
    return n + String(n).split('').reduce((prev, next) => {
        return +prev + +next;
    }, 0);
};

// 주어진 입력들을 이용해서 정답을 반환하는 함수
const flags = Array(10001).fill(false);
const printAnswer = () => {
    let answer = '';
    for(let i=1; i<10001; i++){
        if(!flags[i]){
            let dn = d(i);
            answer += i + '\n';
            while(dn < 10001){
                flags[dn] = true;
                dn = d(dn);
            }
        }
    }
    console.log(answer);
};

// 입력 받아와서 알고리즘 동작하는 함수
const start = (rl) => {
  rl.on('close', () => {
    printAnswer();
    process.exit();
  });
}

// 프로그램 동작
start(rl);


BOJ 10065 - 한수

# 문제

어떤 양의 정수 X의 각 자리가 등차수열을 이룬다면, 그 수를 한수라고 한다. 등차수열은 연속된 두 개의 수의 차이가 일정한 수열을 말한다. N이 주어졌을 때, 1보다 크거나 같고, N보다 작거나 같은 한수의 개수를 출력하는 프로그램을 작성하시오.

# 풀이

이 문제의 경우에는 한수인지 아닌지를 구하는 함수와, 반복문을 돌면서 1부터 N까지 한수를 체크하고 카운팅 하는 함수를 구현하면 쉽게 해결할 수 있는 문제입니다.

// 입출력에 사용할 rl을 받아오는 함수
const getRl = () => {
  const readline = require('readline');
  return readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
}
const rl = getRl();

const isHansoo = num => {
    const splitedNum = String(num).split('');
    return splitedNum.reduce((prev, next, index) => {
        return prev && (index < 2 || +splitedNum[index-2] - +splitedNum[index-1] === +splitedNum[index-1] - +splitedNum[index]);
    }, true)
}

// 주어진 입력을 이용해서 정답을 반환하는 함수
const printAnswer = N => {
    const result =  [...Array(N).keys()].reduce((prev, next) => {
        return isHansoo(next+1) ? prev+1 : prev;
    }, 0);
    console.log(result);
};

// 입력 받아와서 알고리즘 동작하는 함수
const input = [];
const start = (rl) => {
  rl.on('line', line => {
    input.push(parseInt(line));
  }).on('close', () => {
    printAnswer(input[0]);
    process.exit();
  });
}

// 프로그램 동작
start(rl);

댓글0