문제 정의
두 개의 이진수 문자열 str1과 str2를 각각 첫 번째와 두 번째 인자로 받는 JavaScript 함수를 작성해야 합니다.
이 함수는 두 이진수의 합을 반환해야 하며, 단순히 이진수를 십진수로 변환한 뒤 더하는 방식은 사용할 수 없습니다. 또한 최종 결과에는 의미 없는 앞자리 0이 포함되지 않아야 합니다.
예를 들어, 함수의 입력이 다음과 같다면:
입력
const str1 = '1101'; const str2 = '10111';
출력
const output = '100100';
구현 방법
가장 효율적인 접근 방식은 우리가 손으로 이진수 덧셈을 할 때와 동일하게, 가장 낮은 자리부터 한 자리씩 더하면서 올림(carry)을 처리하는 것입니다. 다음은 이 원리를 적용한 코드입니다:
const str1 = '1101';
const str2 = '10111';
const addBinary = (str1 = '', str2 = '') => {
// 문자열을 배열로 분리한 뒤 뒤집어 일의 자리부터 처리
str1 = str1.split('').reverse();
str2 = str2.split('').reverse();
let res = '', temp = 0;
while (str1.length || str2.length || temp) {
// 각 자리 숫자를 더함 (배열이 비면 undefined → 0 처리)
temp += (~~str1.shift()) + (~~str2.shift());
let mod = temp % 2; // 현재 자리의 값
res = mod + res;
temp = temp > 1; // 올림 발생 여부
};
// 앞자리 0 제거, 전부 0이면 '0' 반환
return (+res) ? res.replace(/^0+/, '') : '0';
};
console.log(addBinary(str1, str2));코드 동작 원리
이 코드의 핵심 로직을 단계별로 살펴보면 다음과 같습니다:
1. 자릿수 정렬: split('')으로 문자열을 배열로 만들고 reverse()로 뒤집으면, 일의 자리부터 차례대로 접근할 수 있습니다.
2. 자릿수별 덧셈: while 루프 안에서 shift()로 각 배열의 맨 앞 요소(현재 자리의 숫자)를 꺼내 더합니다. 이때 이중 틸드 연산자 ~~를 사용하면 배열이 이미 비어 있을 때 undefined가 아닌 0으로 처리되므로, 길이가 다른 두 문자열도 안전하게 더할 수 있습니다.
3. 올림 처리: 합계를 2로 나눈 나머지(temp % 2)가 현재 자리의 값이 되고, 합계가 2 이상이면 temp가 true(즉, 1)로 설정되어 다음 자리로 올림이 전달됩니다.
4. 결과 정리: 루프가 끝난 뒤 replace(/^0+/, '')로 앞자리의 불필요한 0을 제거하고, 결과가 빈 값이 되는 경우(모든 자리가 0인 경우)에는 '0'을 반환합니다.
실행 결과
100100
1101(13) + 10111(23) = 100100(36)으로, 십진수 변환 없이 올바른 이진수 덧셈 결과가 출력되는 것을 확인할 수 있습니다.