[프로그래머스] 하샤드 수
해결방안
function solution(x) {
var sum = `${x}`.split('').reduce((acc, cur)=>acc/1 +cur/1);
return x % sum ? false : true;
}
해결방안 순서
- x의 자릿수의 합
- 숫자를 문자열로 만들기 : `${x}`
- 문자열을 각 자릿수로 나누어서 배열로 만들기 : split('')
- 배열의 문자 원소를 숫자 원소로 바꾸고 더해주기 : reduce((acc, cur)=>acc/1 +cur/1)
- 하샤드 수인지 아닌지 확인하기 : return x % sum ? false : true;
1단계. x의 자릿수의 합
1단계_1. 숫자를 문자열로 만들기 : `${x}`
숫자에서는 split()메서드를 쓰면 오류가 나기 때문에 문자열로 바꾸어 주어야 됩니다.
그래서 저는 간단하게 "템플릿 리터럴"를 사용해서 바꾸어 주었습니다.
템플릿 리터럴 ("template strings" (템플릿 문자열))
- ES6부터 새로 도입된 문자열 표기법입니다.
- 문자열 생성 시 따옴표 대신, 백틱(`)을 사용합니다.
- ${ } 사이에 변수나 연산 등을 삽입할 수 있습니다.
테스트 1 (x = 10)
`${x}` -> '10'
테스트 2 (x = 12)
`${x}` -> '12'
테스트 3 (x = 11)
`${x}` -> '11'
테스트 4 (x = 13)
`${x}` -> '13'
1단계_2. 문자열을 각 자릿수로 나누어서 배열로 만들기 : split('')
split()메서드를 사용하여 각 자릿수를 나누어 배열로 만들어 주었습니다.
MDN Web Docs
split() 메서드는 String 객체를 지정한 구분자를 이용하여 여러 개의 문자열로 나눕니다.
구문 : str.split([separator[, limit]])
- separator Optional
원본 문자열을 끊어야 할 부분을 나타내는 문자열을 나타냅니다. 실제 문자열이나 정규표현식을 받을 수 있습니다. 문자열 유형의 separator가 두 글자 이상일 경우 그 부분 문자열 전체가 일치해야 끊어집니다. separator가 생략되거나 str에 등장하지 않을 경우, 반환되는 배열은 원본 문자열을 유일한 원소로 가집니다. separator가 빈 문자열일 경우 str의 각각의 문자가 배열의 원소 하나씩으로 변환됩니다. - limit Optional
끊어진 문자열의 최대 개수를 나타내는 정수입니다. 이 매개변수를 전달하면 split() 메서드는 주어진 separator가 등장할 때마다 문자열을 끊지만 배열의 원소가 limit개가 되면 멈춥니다. 지정된 한계에 도달하기 전에 문자열의 끝까지 탐색했을 경우 limit개 미만의 원소가 있을 수도 있습니다. 남은 문자열은 새로운 배열에 포함되지 않습니다.
// split 예제
var myString = 'Hello World. How are you doing?';
var splits = myString.split(' ', 3);
console.log(splits); //["Hello", "World.", "How"]
// limit를 안 쓸 경우
let mystring = 'Hello';
console.log(mystring.split('')); // [ 'H', 'e', 'l', 'l', 'o' ]
테스트 1 (x = 10)
`${x}` -> '10'
split('') -> ['1', '0']
테스트 2 (x = 12)
`${x}` -> '12'
split('') -> ['1', '2']
테스트 3 (x = 11)
`${x}` -> '11'
split('') -> ['1', '1']
테스트 4 (x = 13)
`${x}` -> '13'
split('') -> ['1', '3']
1단계_3. 배열의 문자원소를 숫자원소로 바꾸고 더해주기 : reduce((acc, cur)=>acc/1 +cur/1)
저번에 쓴 [프로그래머스] 평균 구하기에서 배열원소의 합을 구하려면 reduce를 쓰라고 했습니다.
MDN Web Docs
reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
reduce() 함수는 네 개의 인자를 가집니다.
1. 누산기 (acc)
2. 현재 값 (cur)
3. 현재 인덱스 (idx)
4. 원본 배열 (src)
구문 : 배열.reduce((callback)=>처리할 현재 요소, 기본값)
- callback : 배열의 각 요소에 대해 실행할 함수. 다음 네 가지 인수(acc, cur, idx, src)를 받습니다.
- 기본값 : 넣어도 되고 안 넣어도 됨
// reduce() 메서드 예제
const array1 = [1, 2, 3, 4];
const reducer = (previousValue, currentValue) => previousValue + currentValue; // 1 + 2 + 3 + 4
console.log(array1.reduce(reducer)); // 10
그러나 reduce((acc, cur)=>acc +cur) 이렇게 쓰시면
- ['1', '0'] reduce((acc, cur)=>acc +cur) -> '10'
합이 구해지는게 아니라 문자열로 합쳐질 겁니다.
그래서 문자를 숫자로 바꾸어야 되는데요.
다양한 메소드가 있겠지만 간단하게 "문자열과 숫자열의 사칙연산"으로 숫자를 구해주었습니다.
문자열과 숫자열의 사칙연산은 숫자가 나오게 됩니다.
- '5'/1 = 5
전에는 굳이 map() 메서드를 넣어서 바꾸어 줬지만
reduce()메서드 안에서 바꾸는 방법도 있다는 걸 왜 이제 깨달았는지😅문자열과 숫자열의 사칙연산 한 값을 reduce()메서드에 넣어주시면 됩니다.
- reduce((이전 원소, 현재 원소) => 이전원소/1 + 현재원소/1)
- reduce((acc, cur)=>acc/1 +cur/1)
테스트 1 (x = 10)
`${x}` -> '10'
split('') -> ['1', '0']
reduce((acc, cur)=>acc/1 +cur/1)
-> reduce((0, '1')=> 0/1 +'1'/1) -> 0+1 = 1
-> reduce((1, '0')=> 1/1 +'0'/1) -> 1+0 = 1
sum = 1
테스트 2 (x = 12)
`${x}` -> '12'
split('') -> ['1', '2']
reduce((acc, cur)=>acc/1 +cur/1)
-> reduce((0, '1')=> 0/1 +'1'/1) -> 0+1 = 1
-> reduce((1, '2')=> 1/1 +'2'/1) -> 1+2 = 3
sum = 3
테스트 3 (x = 11)
`${x}` -> '11'
split('') -> ['1', '1']
reduce((acc, cur)=>acc/1 +cur/1)
-> reduce((0, '1')=> 0/1 +'1'/1) -> 0+1 = 1
-> reduce((1, '1')=> 1/1 +'1'/1) -> 1+1 = 2
sum = 2
테스트 4 (x = 13)
`${x}` -> '13'
split('') -> ['1', '3']
reduce((acc, cur)=>acc/1 +cur/1)
-> reduce((0, '1')=> 0/1 +'1'/1) -> 0+1 = 1
-> reduce((1, '3')=> 1/1 +'3'/1) -> 1+3 = 4
sum = 4
2단계. 하샤드 수인지 아닌지 확인하기 : return x % sum ? false : true;
하샤드 수인지 아닌지 확인하기 위해 삼항 연산자를 써주었습니다.
삼항 연산자
구문 : 조건 ? true : false
- 조건이 true이면 true를 실행
- 조건이 false이면 false를 실행
문제 설명에서 "양의 정수 x가 하샤드 수이려면 x의 자릿수의 합으로 x가 나누어져야 합니다."라는 문구가 있습니다.
이 말은 1단계에서 x의 자릿수의 합을 구했으니까
1단계의 값을 가지고 x가 나누어지면 true를 아니면 false를 반환해야 됩니다.
그래서 삼항 연산자에서는
- x의 자릿수의 합 / x ? false : true
이렇게 되고
x의 자릿수의 합은 sum 임으로 조건에
- sum / x
를 해주시면 됩니다.
여기서 왜 x % sum === 0 ? true : false;가 아닌 x % sum ? false : true;로 해준 이유는요.
x % sum === 0이야지 하샤드 수가 됩니다.
이 말은 하샤드 수이면 x % sum에서 무조건 0이 나오게 됩니다.
자바스크립트에서는 Truthy, Falsy값이 있습니다.
여기서 0은 falsy값이기 때문에 조건에서 0이 나오면 false값이 나오게 됩니다.
그래서 x % sum === 0 ? true : false;가 아닌 x % sum ? false : true;로 해줘도 충분히 잘 나오기 때문에 이렇게 써주었습니다.
Truthy, Falsy값에 대해서 알고 싶으시면 아래 링크에서 살펴보시면 될 것 같습니다.👇
기억해야 할 6가지 falsy 값
Javascript 엔진은 boolean 타입이 아닌 값을 Truthy(참으로 평가되는 값), 또는 Falsy(거짓으로 평가되는 값)으로 구분한다. 조건문이나 반복문같은 제어문의 조건식에서는 boolean값으로 평가되는 문맥을
joooing.tistory.com
테스트 1 (x = 10)
sum = 1
x % sum ? false : true -> 10 % 1 ? false : true -> 조건이 0임으로 false로 -> true
테스트 2 (x = 12)
sum = 3
x % sum ? false : true -> 12 % 3 ? false : true -> 조건이 0임으로 false로 -> true
테스트 3 (x = 11)
sum = 2
x % sum ? false : true -> 11 % 2 ? false : true -> 조건이 0이 아니므로 true로 -> false
테스트 4 (x = 13)
sum = 4
x % sum ? false : true -> 13 % 4 ? false : true -> 조건이 0이 아니므로 true로 -> false
여기까지 프로그래머스 하샤드 수 해결방안에 대해 설명해보았습니다.