[JS] BOJ 4344번 평균은 넘겠지

yeopto·2022년 1월 16일
0

Algorithm

목록 보기
5/11
post-thumbnail

출처

BOJ

https://www.acmicpc.net/problem/4344

문제

대학생 새내기들의 90%는 자신이 반에서 평균은 넘는다고 생각한다. 당신은 그들에게 슬픈 진실을 알려줘야 한다.

나의 풀이

const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
let input = fs.readFileSync(filePath).toString().split('\n');

let num = Number(input[0]);

solution();

function solution() {
    for (let i = 1; i <= num; i++) {
        let score = input[i].split(' ');
        let num2 = Number(score.shift());
        let count = 0;

        let avg = score.reduce((acc, v) => acc += Number(v), 0);
        
        avg /= num2;
    
        for (let j = 0; j < num2; j++) {
            if (score[j] > avg) {
                count++;
            }
        }
        let result = ((count / num2) * 100).toFixed(3);
        
        console.log(result + "%");
    }
}

입력 첫번째 줄(input[0])은 테스트 케이스 개수 → 두번째 줄(input[1])부터 테스트케이스 만큼 반복할건데, 한 줄씩 출력 후 다음 반복으로 넘어갈 예정. → 일단 split 사용 하여 공백기준으로 input[i]를 쪼개 줌 → shift사용해서 score 첫번째 요소인 학생 수를 num2로 할당 → count는 평균 넘는 학생들을 찾을때마다 증가시킬 예정 → reduce로 학생들 평균구하기전 총합을 구하고 num2만큼 나눠서 avg를 구함. → shift로 첫번째 요소를 뺏기 때문에 score는 점수들의 배열로만 이루어져 있음 → 점수 배열들을 학생 수인 num2만큼 반복해서 점수가 평균보다 높으면 count를 1씩 증가 시켜줌 → 증가된 count 수를 학생 수 만큼 나눠서 x100을 하면 평균넘는 학생들의 비율을 구할 수 있음 → toFixed로 소수점 셋째 자리까지 출력하게함 → 한줄 출력 뒤 다음 줄을 똑같이 반복해서 테스트케이스만큼 평균넘는 학생 비율을 출력.

reduce

  1. reduce 메서드는 두 개의 파라미터를 가짐. (콜백함수, 초기누산값)
  2. reduce는 forEach와 map과 달리 누산값이라는 콜백함수의 누산값이라는 첫번째 파라미터가 있음. 콜백 함수가 동작할 때 return하는 값이 다음 콜백 함수의 첫 번째 파라미터로 전달 됨. 마지막 콜백 함수가 동작한 이후의 return값이 reduce 메서드의 return 값이 된다. 나머지 2,3,4번째 파라미터는 map, forEach 메서드의 1,2,3번째 파라미터와 역할이 동일함. 그래서 reduce의 콜백 함수의 파라미터 생략은 3,4번째만 가능함.
  3. reduce 메서드의 두 번째 파라미터는 초기누산값인데, 콜백함수가 동작하면서 해당 함수의 리턴값이 다음 콜백함수의 첫번째 파라미터로 전달되는데, 이 원리대로라면 가장 첫 번째 동작하는 콜백함수의 첫 번째 파라미터는 전달 받는 값이 없다. 그래서 reduce 메서드의 두번째 파라미터에, 첫 번째 콜백함수에서 동작할 누산값을 전달해 주는 것.
  4. reduce 메서드의 초기누산값이라 불리는 두 번째 파라미터는 생략이 가능하긴한데, 두번째 파라미터를 생략하고 콜백 함수만 전달할 경우, 배열의 첫 번째 요소(0번째 index)가 초기값이 되어 동작하게 된다. 0번째 index가 초기값이 되기 때문에 0번째 콜백 함수는 동작하지 않게 됨. 즉, 배열의 길이 -1 만큼 콜백 함수가 동작함 → 이래나 저래나 결과가 똑같다면 상관 없겠지만 콜백 함수의 동작 횟수에 따라 결과에 차이가 있을법한 경우라면 오류로 이어질 수 있기 때문에, 생략하지 않는 것이 권장.
const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
let input = fs.readFileSync(filePath).toString().split('\n');

let num = Number(input[0]);

solution();

function solution() {
    for (let i = 1; i <= num; i++) {
        let score = input[i].split(' ').map(x => Number(x));
        let num2 = score.shift();
        let count = 0;

        let avg = score.reduce((acc, v) => acc += v);
        
        avg /= num2;
    
        for (let j = 0; j < num2; j++) {
            if (score[j] > avg) {
                count++;
            }
        }
        let result = ((count / num2) * 100).toFixed(3);
        
        console.log(result + "%");
    }
}

reduce 메서드의 두번째 파라미터를 제외한 코드다. 위의 나의 풀이에서 두번째 파라미터 초기값을 제외해버리면 score의 0번째 인덱스가 초기값이 되는데 타입이 string이라서 콜백함수 return이 “50” + 50으로 “5050”되어버린다. (문자열 + 숫자는 문자열이 반환됨) 그래서 score를 선언해줄때 map으로 Number을 적용시킨 숫자들의 배열로 만든 뒤 reduce에 요소들을 인자로 보내주면 두번째 파라미터를 생략해도 나의 풀이와 똑같이 작동한다. → 이 경우엔 가능하지만 콜백 함수 동작 횟수에 따라 결과가 차이 있을 경우면 오류로 이어지기에 웬만하면 생략하지말자.

profile
https://yeopto.github.io로 이동했습니다.

0개의 댓글