Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript로 자릿수 합을 기준으로 배열의 숫자 정렬하기

문제 개요

JavaScript에서 양의 정수로 이루어진 배열 arr를 입력받아, 각 숫자의 자릿수 합(digit sum)이 큰 숫자부터 작은 숫자 순서대로 내림차순 정렬하는 함수를 작성해야 합니다.

예를 들어, 다음과 같은 배열이 입력으로 주어졌다고 가정해 보겠습니다.

입력

const arr = [5, 34, 1, 13, 76, 8, 78, 101, 57, 565];

출력

const output = [565, 78, 76, 57, 8, 34, 5, 13, 101, 1];

출력 결과 분석

  • 565 → 5 + 6 + 5 = 16 (가장 큰 자릿수 합)
  • 78 → 7 + 8 = 15
  • 76 → 7 + 6 = 13
  • 57 → 5 + 7 = 12
  • 88, 34 → 3 + 4 = 7, 55
  • 13 → 1 + 3 = 4, 101 → 1 + 0 + 1 = 2, 11 (가장 작은 자릿수 합)

즉, 자릿수 합이 16인 565가 첫 번째로 오고, 자릿수 합이 각각 2와 1로 가장 작은 101과 1이 마지막에 위치하게 됩니다.

접근 방법

이 문제는 크게 두 단계로 나누어 해결할 수 있습니다.

  1. 자릿수 합 계산 함수 작성: 주어진 숫자의 각 자릿수를 더하는 재귀 함수를 만듭니다. 숫자를 10으로 나눈 나머지(% 10)로 일의 자리를 추출하고, 10으로 나눈 몫(Math.floor(num / 10))으로 다음 자릿수로 이동하는 방식입니다.
  2. 정렬 수행: 배열의 sort() 메서드에 비교 함수(comparator)를 전달하여, 두 숫자의 자릿수 합 차이를 기준으로 내림차순 정렬합니다.

코드 구현

다음은 위 접근 방식을 구현한 전체 코드입니다.

const arr = [5, 34, 1, 13, 76, 8, 78, 101, 57, 565];

// 숫자의 자릿수 합을 재귀적으로 계산하는 함수
const addDigits = (num, sum = 0) => {
   if(num){
      return addDigits(Math.floor(num / 10), sum + (num % 10));
   };
   return sum;
};

// 자릿수 합을 기준으로 내림차순 정렬하는 함수
const sortByDigitSum = (arr = []) => {
   arr.sort((a, b) => {
      return addDigits(b) - addDigits(a);
   });
   return arr;
};

sortByDigitSum(arr);
console.log(arr);

출력 결과

[ 565, 78, 76, 57, 8, 34, 5, 13, 101, 1 ]

코드 상세 설명

1. addDigits 함수

addDigits는 재귀 호출을 활용한 자릿수 합 계산기입니다.

  • num % 10: 현재 숫자의 마지막 자릿수(일의 자리)를 추출합니다.
  • Math.floor(num / 10): 마지막 자릿수를 제거한 나머지 부분을 반환합니다.
  • 숫자가 0이 되면 누적된 sum을 최종 결과로 반환하며 재귀가 종료됩니다.

예를 들어 addDigits(565)는 5 + 6 + 5 = 16을 반환합니다.

2. sortByDigitSum 함수와 sort() 비교 로직

JavaScript의 Array.prototype.sort()는 비교 함수의 반환값에 따라 요소의 순서를 결정합니다.

  • 반환값이 양수이면 ab 뒤로 정렬됩니다.
  • 반환값이 음수이면 ab 앞으로 정렬됩니다.
  • 반환값이 0이면 순서가 유지됩니다.

여기서는 addDigits(b) - addDigits(a)를 반환하므로, 자릿수 합이 큰 숫자(b)가 앞쪽에 배치되는 내림차순 정렬이 수행됩니다. 만약 오름차순 정렬이 필요하다면 addDigits(a) - addDigits(b)로 부호만 반전시키면 됩니다.

참고: 반복문 기반 대안 구현

재귀 대신 반복문으로 자릿수 합을 계산하고 싶다면 다음과 같이 작성할 수도 있습니다.

const addDigitsIterative = (num) => {
   let sum = 0;
   while (num > 0) {
      sum += num % 10;
      num = Math.floor(num / 10);
   }
   return sum;
};

또는 문자열 변환을 활용한 간결한 방법도 있습니다.

const addDigitsString = (num) =>
   String(num).split('').reduce((sum, digit) => sum + Number(digit), 0);

세 가지 방식 모두 동일한 결과를 반환하지만, 재귀 방식은 깊은 재귀 호출 시 콜 스택 오버플로우 가능성이 있으므로 매우 큰 숫자를 다룰 때는 반복문 방식이 더 안전합니다.