프로그래머스 - 위클리 챌린지 2주차 : 상호평가

3 minute read

문제는 여기

  1. i행 j열의 값은 i번 학생이 평가한 j번 학생의 과제 점수입니다.
    -> j번 학생의 점수를 구하려면 j열의 값들을 조사해야한다.
  2. 학생들이 자기 자신을 평가한 점수가 유일한 최고점 또는 유일한 최저점이라면 그 점수는 제외하고 평균을 구합니다.
    -> 최대/최소 점수를 구해야하고, 해당 점수가 유일한지 검사해야한다.

솔루션

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