프로그래머스 - 위클리 챌린지 6주차 : 복서 정렬하기
- 전체 승률이 높은 복서의 번호가 앞쪽으로 갑니다. 아직 다른 복서랑 붙어본 적이 없는 복서의 승률은 0%로 취급합니다.
- 승률이 동일한 복서의 번호들 중에서는 자신보다 몸무게가 무거운 복서를 이긴 횟수가 많은 복서의 번호가 앞쪽으로 갑니다.
- 자신보다 무거운 복서를 이긴 횟수까지 동일한 복서의 번호들 중에서는 자기 몸무게가 무거운 복서의 번호가 앞쪽으로 갑니다.
- 자기 몸무게까지 동일한 복서의 번호들 중에서는 작은 번호가 앞쪽으로 갑니다.
※ 승부를 하지 않은 경우 승률계산에서 제외되어야한다. ‘NNWN’ 이면 승률 100%
솔루션
function solution(weights, head2head) {
const compare = (b1, b2) =>
b1.winRate != b2.winRate ? b2.winRate - b1.winRate
: b1.expensiveWin != b2.expensiveWin ? b2.expensiveWin - b1.expensiveWin
: b1.weight != b2.weight ? b2.weight - b1.weight
: b1.index - b2.index
;
const boxer = head2head.map((v, me) => {
let winCnt = 0;
let expensiveWinCnt = 0;
let vsCnt = v.length;
const arr = v.split('');
arr.forEach((element, other) => {
if(element == 'N') vsCnt--;
if(element == 'W') {
winCnt++;
if(weights[me] < weights[other]) expensiveWinCnt++;
}
})
return {
'index' : me,
'weight' : weights[me],
'winRate': vsCnt == 0 ? 0 : winCnt/vsCnt,
'expensiveWin': expensiveWinCnt
}
});
return boxer.sort(compare).map(v => v.index+1);
}
const t1 = solution([50,82,75,120],["NLWL","WNLL","LWNW","WWLN"]);
const t2 = solution([145,92,86],["NLW","WNL","LWN"]);
const t3 = solution([60,70,60],["NNN","NNN","NNN"]);
console.log(` t1 : ${t1}, answer : [3,4,1,2]`);
console.log(` t2 : ${t2}, answer : [2,3,1]`);
console.log(` t3 : ${t3}, answer : [2,1,3]`);
Logical OR 연산자를 이용한 Compare 만들기
const compare = (b1, b2) =>
b1.winRate != b2.winRate ? b2.winRate - b1.winRate
: b1.expensiveWin != b2.expensiveWin ? b2.expensiveWin - b1.expensiveWin
: b1.weight != b2.weight ? b2.weight - b1.weight
: b1.index - b2.index
;
if/else if
보다 타이핑량이 적어서 선호하는 다중 삼항 연산자를 이용해서 compare
함수를 만들어서 문제를 풀었다.
다른 사람 풀이를 구경하다가 논리연산자로 이걸 구현한 사람들 발견하고 당황했다.
그러나 &&와 || 연산자는 사실 두 피연산자 중 하나를 반환하는 것으로, 만약 둘 중 하나가 불리언 값이 아니라면 논리 연산자의 반환 값도 불리언 값이 아닐 수 있습니다.
?! 논리연산자는 언제나 피연산자도, 결과도 boolean 일 거라고만 생각하고 살았다…
false로 변환할 수 있는 표현식은 평가 결과가 null, 0, NaN, 빈 문자열(“”), undefined인 경우입니다.
false
로 변환되지 않는 나머지 표현식은 모두 true
라는 뜻으로 해석되는 것 같다. 왜냐면 MDN 페이지 예제에서 아래와 같은 경우에 ‘Cat’을 반환하기 때문이다.
var o5 = "Cat" || "Dog"; // t || t returns Cat
그래서 아래와 같은 방법으로 위와 compare
함수를 똑같이 만들 수 있다. 타이핑량도 더 적고 가독성도 더 좋아보인다.
const compare = (b1, b2) => b2.winRate - b1.winRate
|| b2.expensiveWin - b1.expensiveWin
|| b2.weight - b1.weight
|| b1.index - b2.index
;
b1
와 b2
의 값이 같다면, 결과는 0
이 될 것이고 0
은 false
로 변환될 수 있다. 그러면 ||
연산자는 다음 피연산자를 검사하고 그 결과를 리턴한다.
b1
과 b2
의 값이 다르다면, 결과는 null, 0, NaN, 빈 문자열(""), undefined
가 아니므로 true
로 취급된다. 그러면 ||
연산자는 b1 - b2
의 결과를 리턴한다.
Reference
- https://programmers.co.kr/learn/courses/30/lessons/85002/solution_groups?language=javascript
- https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Expressions_and_Operators