[백준] 4673 - 셀프 넘버 (node.js)

Jang·2022년 9월 12일
0

백준

목록 보기
1/6
post-thumbnail

문제 : https://www.acmicpc.net/problem/4673

최근에 백준을 단계별로 풀기 시작했다.
이 문제에서 약 2시간 정도 헤매고 겨우 푼 다음
숏 코딩을 보게 되었는데 코드에 길이에 당황하고
보고도 이해가 안되서 2차로 당황했다.
그래도 한글자 한글자 나름대로 해석보려고 한다.

본인 코드

let man = [];                   // 1부터 9999까지 모든 정수의 배열 man
for (i = 1; i < 10000; i++) {
  man.push(i);
}

let nonSelf = []; 				// 어떤 수로 인해 생성된 숫자를 담는 배열 (셀프넘버가 아닌 수들)

man.forEach((v, i) => {		    // 1부터 10000까지의 수들이 생성하는 수를 nonSelf에 넣음
  const nn = "" + v;			// v = 원래 수

  let sum = 0;  				// sum = v의 각자릿수를 더한 수
  for (j = 0; j < nn.length; j++) {
    sum += parseInt(nn[j]);
  }

  let x = v + parseInt(sum);
  if (x < 10000) {
    nonSelf.push(x);
  }
});

nonSelf = nonSelf.sort((a, b) => {  	// nonSelf를 오름차순으로 정렬
  if (a > b) {
    return 1;
  } else {
    return -1;
  }
});

for (i = 0; i < man.length; i++) { 		// 셀프 넘버: man의 원소중 nonSelf에 없는 것들을 출력
  if (!nonSelf.includes(man[i])) {
    console.log(man[i]);
  }
}

숏 코딩

i = 0;
a = [];
while (++i < 10001) {
  a[i] ?? (a[i] = 1);
  r = i + ("" + i).split("").reduce((a, b) => +a + +b, 0);
  a[r] = 0;
}
a.forEach((n, i) => n && i != 0 && console.log(i));

// 출처 : https://www.acmicpc.net/source/33710125 (아이디:votmdnjem) 

while (++i < 10001) {

  • i에 1을 더하고, 그 더한 값이 10001보다 작은 동안 {} 안의 내용을 반복실행. (조건문 안에 ++를 써도 되는걸 처음 알았다.)
  • for 문을 안쓰고 while문을 쓴 이유는 i를 마지막에 출력할때 반복문 밖에서 써야 하기 때문에 밖에서 선언할수 있는 while을 쓴 것 같다.
  • i가 1부터 시작하게 되는데 인덱스가 출력할 정수가 같아지게 된다.

a[i] ?? (a[i] = 1);

  • a[i]null or undefined라면 a[i]에 1을 넣음. (1이 들어간 수는 셀프 넘버)

r = i + ("" + i).split("").reduce((a, b) => +a + +b, 0);

  • r : 생성 되는 숫자.
  • i : 원래 값
  • ("" + i).split("").reduce((a, b) => +a + +b, 0)
    • ("" + i).split("") : 숫자 i를 문자열로 만든후 각자리수를 배열로 나눔 (split"" 로도 되는지 처음 알았다.)
    • .reduce((a, b) => +a + +b, 0) : +a와 +b의 뜻을 몰라 찾아봄

      출처 : https://stackoverflow.com/questions/52132654/what-does-a-b-mean-in-javascript

      String타입인 숫자를 parseInt()를 이용하지 않고 더할 수 있는 방법인듯 하다.
      .reduce((a, b) => +a + +b, 0) 는 배열의 모든 숫자를 더한 값.
      그리고 마지막 ,0)의 뜻은

      /** accumulator의 초기값 지정하기 */
      // reduce의 콜백함수 다음에 두 번째 인자로 accumulator의 초기값을 설정할 수 있다.
      // 이 경우 currentValue에는 배열의 0번째 요소부터 전달되고 index는 0부터 시작된다.

      인데 배열의 초기값에 숫자형태를 넣어주기 위함 같은데 굳이 왜넣은지 모르겠다.

      ,0)을 빼고 채점하니 틀렸다고 나온다. 타입이 달라지는듯 하다.

a[r] = 0;

  • a[10] = 10 처럼 배열 a에 인덱스와 같은 정수를 넣고 있는데 생성된 수 (셀프 넘버가 아닌 수)에 0을 넣음.

a.forEach((n, i) => n && i != 0 && console.log(i));

  • 배열 a를 전부 탐색한다. a[i] = n

  • && - 왼쪽 피연산자를 평가해서 falsy이면 이 값을 바로 반환합니다. 아니라면 오른쪽 피연산자를 평가한 결과값을 반환합니 다.

  • 왼쪽 값이 true라면 즉(n과 i가 0이 아니라면) console.log(i)를 실행.

  • n && i != 0에서 굳이 i까지 넣을 필요 없을 것 같아서 n !=0 으로 바꿔서 채점해보니 맞다고 나온다.




마무리

보고도 겨우 이해하는데 직접 저런 코드를 짜려면 많이 노력해야겠다.

0개의 댓글