프로그래머스 - 위클리 챌린지 2주차 : 상호평가
- i행 j열의 값은 i번 학생이 평가한 j번 학생의 과제 점수입니다.
-> j번 학생의 점수를 구하려면 j열의 값들을 조사해야한다. - 학생들이 자기 자신을 평가한 점수가 유일한 최고점 또는 유일한 최저점이라면 그 점수는 제외하고 평균을 구합니다.
-> 최대/최소 점수를 구해야하고, 해당 점수가 유일한지 검사해야한다.
솔루션
function solution(scores) {
const getGrade = score =>
score >= 90 ? 'A' :
score >= 80 ? 'B' :
score >= 70 ? 'C' :
score >= 50 ? 'D' :
'F';
const transpose = matrix => matrix.reduce((result, row) => row.map((e, i) => [...(result[i] || []), e]),[]);
const answer = transpose(scores).reduce((result, row, i)=>{
const onlyMaxFromMe = () => (row[i] == max) && (row.filter(v => v == max).length == 1);
const onlyMinFromMe = () => (row[i] == min) && (row.filter(v => v == min).length == 1);
const max = Math.max(...row);
const min = Math.min(...row);
const sum = row.reduce((acc,v)=>acc+=v,0);
const avg =
onlyMaxFromMe() ? (sum - max) / (row.length-1) :
onlyMinFromMe() ? (sum - min) / (row.length-1) :
sum / row.length;
return result += getGrade(avg);
},"");
return answer;
}
전치행렬 만들기
- 전치행렬 : 행과 열이 바뀐 행렬
const transpose = matrix => matrix.reduce((result, row) => row.map((e, i) => [...(result[i] || []), e]),[]);
matrix(2차원배열)의 각각의 row마다 map 함수를 이용해서 reduce 함수로 새로만든 이차원배열 []
에 행과 열을 바꾸어 값을 넣어준다.
예시
- result :
[]
(reduce()의 initialValue 인자로 받음) - matrix :
[ [100, 90, 98, 88, 65], [50, 45, 99, 85, 77], [47, 88, 95, 80, 67], [61, 57, 100, 80, 65], [24, 90, 94, 75, 65] ]
1. [100, 90, 98, 88, 65].map((e,i) => [...[], e])
[
[...[], 100],
...
]
result :
[
[100],
[90],
[98],
[88],
[65]
]
2. [50, 45, 99, 85, 77].map((e,i) => [...result[i], e])
[
[...[100], 50],
...
]
result :
[
[100, 50],
[90, 45],
[98, 99],
[88, 85],
[65, 77]
]
3. [47, 88, 95, 80, 67].map((e,i) => [...result[i], e])
[
[...[100, 50], 47],
...
]
result :
[
[100, 50, 47],
[90, 45, 88],
[98, 99, 95],
[88, 85, 80],
[65, 77, 67]
]
4. [61, 57, 100, 80, 65].map((e,i) => [...result[i], e])
[
[...[100, 50, 47], 61],
...
]
result :
[
[100, 50, 47, 61],
[90, 45, 88, 57],
[98, 99, 95, 100],
[88, 85, 80, 80],
[65, 77, 67, 65]
]
5. [24, 90, 94, 75, 65].map((e,i) => [...result[i], e])
[
[...[100, 50, 47, 61], 24],
...
]
result :
[
[100, 50, 47, 61, 24],
[90, 45, 88, 57, 90],
[98, 99, 95, 100, 94],
[88, 85, 80, 80, 75],
[65, 77, 67, 65, 65]
]
Math.max()
- 입력값으로 받은 0개 이상의 숫자 중 가장 큰 숫자를 반환한다.
- 만약 인수 중 하나라도 숫자로 변환하지 못한다면
NaN
을 반환한다. - 매개변수를 제공하지 않은 경우
-Infinity
를 반환한다.
Math.max() //-Infinity
Math.max(값0)
Math.max(값0, 값1)
Math.max(값0, 값1, ... , 값N)
배열의 요소들을 인자로 넣어주고 싶으면 다음과 같이 apply()
또는 spread operator
를 사용할 수 있다.
const arr = [1, 2, 3];
const max1 = Math.max.apply(null,arr); //apply() 사용
const max2 = Math.max(...arr); //spread operator 사용
배열의 요소가 많아서 Math.max() 함수에 인자가 너무 많아질 경우 RangeError: Maximum call stack size exceeded
에러가 발생하며 잘못된 결과를 반환한다.
const arr = [...Array(10000000).keys()];
console.log(arr);
/*
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 9999900 more items
]
*/
console.log(Math.max(...arr));
// RangeError: Maximum call stack size exceeded
이런 경우 reduce 함수를 이용하면 Math 객체도 이용하지 않고, 메모리 소모도 더 적으면서 정확한 결과를 얻을 수 있다.
arr.reduce((a, b) => a > b ? a : b);
Reference
- https://velog.io/@dyongdi/JS-2%EC%B0%A8%EC%9B%90-%EB%B0%B0%EC%97%B4%EC%9D%98-%ED%96%89%EA%B3%BC-%EC%97%B4-%EB%B0%94%EA%BE%B8%EA%B8%B0-Transposing-a-2D-array-in-JavaScript
- https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/max
- https://blog.naver.com/PostView.nhn?blogId=helicopter55&logNo=221873799599
- https://programmingsummaries.tistory.com/108