[JavaScript] 백준 KCPC (JS)

SanE·2024년 3월 28일

Algorithm

목록 보기
77/127

쇠막대기

📚 문제 설명


N개의 팀이 K개의 문제를 푼다고 한다.
각각의 팀이 받은 점수의 총합으로 등수를 나눈다고 할 때,
내가 속한 T팀의 등수는 몇등인가?

단, 두 팀의 점수가 같을 경우 다음 규칙에 의해서 순위가 정해진다.

  1. 최종 점수가 같은 경우, 풀이를 제출한 횟수가 적은 팀의 순위가 높다.
  2. 최종 점수도 같고 제출 횟수도 같은 경우, 마지막 제출 시간이 더 빠른 팀의 순위가 높다.

👨🏻‍💻 풀이 과정


각각의 팀에 대한 정보를 저장할 Team 클래스를 만들었다.
Team 클래스는 아래와 같은 요소를 가지고 있다.

  • 성적을 저장할 score 배열
  • 풀이를 제출한 횟수 cnt
  • 마지막 제출 시간 lastOrder

그 외에도 풀이를 제출하면 score에 저장을 할 함수 SetScore()을 만들었고
최종적으로 비교를 위해 정보를 리턴해줄 GetTatal() 함수를 만들었다.

Team class

    class Team {
        constructor(length) {
          	// 점수 저장 배열
            this.score = new Array(length).fill(0);
          	// 풀이 제출 횟수
            this.cnt = 0;
          	// 마지막 제출 시기
          	// 10,000개의 로그가 최대이기 때문에 10,000으로 초기화.
            this.lastOrder = 10000;
        }
		// 점수 저장 함수
        SetScore(Num, Score, LastOrder) {
          	// 제출한 점수가 높을 때만 갱신.
            if (this.score[Num - 1] < Score) {
                this.score[Num - 1] = Score;
            }
          	// 제출 횟수 증가
            this.cnt++;
          	// 제출 시기 갱신.
            this.lastOrder = LastOrder;
        }
		// 정보 리턴
        GetTotal() {
          	// 점수 총합.
            let total = this.score.reduce((acc, cur) => {
                return acc + cur;
            }, 0);
          	// 점수 총합, 제출 횟수, 마지막 제출 시기
            return [total, this.cnt, this.lastOrder];
        }
    }

이후에는 간단하다.
각각의 팀 정보를 저장할 배열에 팀 객체를 넣어주면 된다.
예시를 들면 [new Team(), new Team(), .....] 이런식이다.

이제 각각의 로그를 확인하여 점수를 갱신한 후에 T팀보다 점수가 높은 팀이 몇개인지 세주면 된다.

등수 계산 함수

    const CalculateMyScore = (N, K, T, M) => {
      	// 로그 저장.
        const SubmitLists = input.splice(0, M).map(v => v.split(' ').map(Number));
		// 팀 갯수만큼 배열 생성.
      	const Teams = new Array(N);
      	// 등수
        let answer = 1;
      
        for (let i = 0; i < Teams.length; i++) {
            Teams[i] = new Team(K);
        }
      	// 로그 확인 후 각각의 팀에 점수 갱신.
        for (let i = 0; i < SubmitLists.length; i++) {
            const [TeamId, Num, Score] = SubmitLists[i];
            Teams[TeamId - 1].SetScore(Num, Score, i);
        }
      	// 내팀의 점수
        const My = Teams[T - 1].GetTotal();
      	// 우리팀보다 높은 점수의 팀 확인.
        for (let i = 0; i < Teams.length; i++) {
            if (i !== T - 1) {
                const Compare = Teams[i].GetTotal();
                if (Compare[0] > My[0]) {
                    answer++;
                    continue;
                } else if (Compare[0] === My[0]) {
                    if (Compare[1] < My[1]) {
                        answer++;
                        continue;
                    } else if (Compare[1] === My[1]) {
                        if (Compare[2] < My[2]) {
                            answer++
                            continue;
                        }
                    }
                }
            }
        }
        return answer;
    };

이제 테스트 케이스만큼 위의 함수를 진행시킬 함수를 생성하면 끝이다.

전체 코드

    let fs = require("fs");
    let input = fs.readFileSync("/dev/stdin").toString().trim().split("\n");
    const TestCase = parseInt(input.shift());

    class Team {
        constructor(length) {
          	// 점수 저장 배열
            this.score = new Array(length).fill(0);
          	// 풀이 제출 횟수
            this.cnt = 0;
          	// 마지막 제출 시기
          	// 10,000개의 로그가 최대이기 때문에 10,000으로 초기화.
            this.lastOrder = 10000;
        }
		// 점수 저장 함수
        SetScore(Num, Score, LastOrder) {
          	// 제출한 점수가 높을 때만 갱신.
            if (this.score[Num - 1] < Score) {
                this.score[Num - 1] = Score;
            }
          	// 제출 횟수 증가
            this.cnt++;
          	// 제출 시기 갱신.
            this.lastOrder = LastOrder;
        }
		// 정보 리턴
        GetTotal() {
          	// 점수 총합.
            let total = this.score.reduce((acc, cur) => {
                return acc + cur;
            }, 0);
          	// 점수 총합, 제출 횟수, 마지막 제출 시기
            return [total, this.cnt, this.lastOrder];
        }
    }

    const CalculateMyScore = (N, K, T, M) => {
      	// 로그 저장.
        const SubmitLists = input.splice(0, M).map(v => v.split(' ').map(Number));
		// 팀 갯수만큼 배열 생성.
      	const Teams = new Array(N);
      	// 등수
        let answer = 1;
      
        for (let i = 0; i < Teams.length; i++) {
            Teams[i] = new Team(K);
        }
      	// 로그 확인 후 각각의 팀에 점수 갱신.
        for (let i = 0; i < SubmitLists.length; i++) {
            const [TeamId, Num, Score] = SubmitLists[i];
            Teams[TeamId - 1].SetScore(Num, Score, i);
        }
      	// 내팀의 점수
        const My = Teams[T - 1].GetTotal();
      	// 우리팀보다 높은 점수의 팀 확인.
        for (let i = 0; i < Teams.length; i++) {
            if (i !== T - 1) {
                const Compare = Teams[i].GetTotal();
                if (Compare[0] > My[0]) {
                    answer++;
                    continue;
                } else if (Compare[0] === My[0]) {
                    if (Compare[1] < My[1]) {
                        answer++;
                        continue;
                    } else if (Compare[1] === My[1]) {
                        if (Compare[2] < My[2]) {
                            answer++
                            continue;
                        }
                    }
                }
            }
        }
        return answer;
    };
	
    const solution = () => {
        let answer = [];
      	// 테스트 케이스만큼 진행.
        for (let i = 0; i < TestCase; i++) {
            const [N, K, T, M] = input.shift().split(' ').map(Number);
            answer.push(CalculateMyScore(N, K, T, M));
        }
        console.log(answer.join('\n'));
    };
    solution();

🧐 후기


이렇게 코드를 제출하고 다른 사람들의 풀이를 확인해 보니 다들 나보다 코드 줄 수가 적었다. 그러나 전체적인 풀이는 비슷했고 개인적으로 내 코드가 더 마음에 들어서 굳이 수정하지는 않았다. 실력을 더 닦고 나서 다시 확인한 후에 내 코드가 수정이 필요하다고 생각하면 그때 수정할듯하다.

profile
JavaScript를 사용하는 모두를 위해...

0개의 댓글