[백준 4344번] - 평균은 넘겠지 (Java)

uHan2·2020년 3월 17일
4

TIL.Algorithm

목록 보기
3/12
post-custom-banner

안녕하세요.
지금까지 계속 저만의 기술 블로그를 만들어야지, 만들거야
마음으로만 다짐하다가 인제야 시작하게 되었습니다.
비록 시작은 코딩일기지만, 그 끝은 창대하게
어엿한 개발자 블로그로 성장할 수 있도록 노력하겠습니다.


Prologue

안녕하세요!
요즘 코로나바이러스로 다들 힘드실 겁니다.
하지만 역설적으로 이럴 때일수록 더 힘내시길 바랍니다.

두 번째 일기네요.
오늘은 문제 이름부터 조금은 슬픈 문제를 가져와 보았습니다.

백준 4344번 평군은 넘겠지

문제는 단 한 줄, 매우 짧습니다.
열심히 공부하여 대학에 들어온 새내기들에게 현실을 깨닫게 해주는 문제죠..
개인적으로 저도 평균 넘기기 너무 어려운 것 같아요 ㅠㅠ 의지 부족..

난이도 자체는 낮다고 생각합니다 만 입출력 부분의 코딩과 조건에 맞게 출력하는
부분이 낮은 정답률 38% 의 요인이 되지 않았나 생각합니다.


PseudoCode

처음 문제를 봤을 때 들었던 생각은

1. 테스트 케이스를 입력받아 그 크기만큼 while문 돌리기

2. 각 테스트 케이스의 학생 수와 점수들을 입력받기

3. 각각의 평균을 계산하고, 평균을 넘는 학생 수의 비율을 배열에 따로 저장

4. 각각의 평균을 넘는 학생 비율을 조건에 맞는 형식으로 출력(소수점)

입니다.

사실 논리적으로 어려운 부분은 없고 에러 없이 잘 입력받고, 잘 출력하면 되는 문제라고 생각하여 크게 어려움은 없었습니다. 다만, 뒤에서 다시 한 번 말씀드리겠지만 소수점 셋째 자리까지 반올림하여 출력하는 부분이 학습 포인트라고 생각했습니다.


SourceCode

import java.io.*;
import java.util.*;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        int testCase = Integer.parseInt(br.readLine());
        int count = 0;
        int average = 0;
        int sum = 0;

        int avgCount = 0;
        
        double ratio = 0;
        
        int[] arr = null;
        double[] ratioArr = new double[testCase];
        
        while(count < testCase)
        {
            StringTokenizer str = new StringTokenizer(br.readLine());
            
            int eachCase = Integer.parseInt(str.nextToken());
            
            arr = new int [eachCase];
            ratio = 0;
            sum = 0;
            avgCount = 0;
            
            for(int i = 0 ; i < arr.length ; i++)
            {
                arr[i] = Integer.parseInt(str.nextToken());
                sum += arr[i];
            }
            
            average = sum / eachCase;
            
            for(int i = 0 ; i < arr.length ; i++)
            {
                if(arr[i] > average)
                {
                    avgCount++;
                }
            }
            
            ratio = (double) avgCount / (double) eachCase * (double) 100;
            
            ratioArr[count] = ratio;
            
            count++;
            
        }
        
        for(int i = 0 ; i < testCase ; i++)
        {
            System.out.println(String.format("%.3f", ratioArr[i]) + "%");
        }
        
    }
}

(언제나처럼 코드리뷰! 부탁드립니다!)

입력받고 값을 처리하는 부분에서 별다른 에러가 없다면
크게 어려움 없는 문제인 만큼 코드 길이도 짧습니다.

코드를 살펴보면,


BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

int testCase = Integer.parseInt(br.readLine());
int count = 0;
int average = 0;
int sum = 0;
int avgCount = 0;
double ratio = 0;

int[] arr = null;
double[] ratioArr = new double[testCase];

우선 필요한 변수들을 몇 가지 선언 및 초기화하는 파트입니다.
값을 입력받을 때는 BufferedReader를 이용하였습니다.

변수들로는,

  • 학생들의 점수를 입력받는 배열 arr
  • 평균을 넘는 학생의 비율을 저장하는 배열 ratioArr
  • 테스트 케이스의 크기만큼 반복하는 트리거와, ratioArr인덱스 역할을 하는 count
  • 평균을 구하기 위한 변수들 average, sum, avgCount 등이 있습니다.

while(count < testCase)
{
    StringTokenizer str = new StringTokenizer(br.readLine());
            
    int eachCase = Integer.parseInt(str.nextToken());
         
     arr = new int [eachCase];
     ratio = 0;
     sum = 0;
     avgCount = 0;
            
     for(int i = 0 ; i < arr.length ; i++)
     {
         arr[i] = Integer.parseInt(str.nextToken());
         sum += arr[i];
     }
            
     average = sum / eachCase;
            
     for(int i = 0 ; i < arr.length ; i++)
     {
          if(arr[i] > average)     
          {
               avgCount++;
          }
      }
            
     ratio = (double) avgCount / (double) eachCase * (double) 100;
            
     ratioArr[count] = ratio;
            
     count++;
            
     }

다음은 반복문 while문 내부의 코드입니다.

  1. 우선 학생 수와 점수들은 공백을 기준으로 입력받습니다. 그렇기 때문에 StringTokenizer 을 이용하여 학생 수를 입력받아 변수 eachCase에 대입하고, 점수들을 입력받을 배열 arr 의 크기를 할당해줍니다.

  2. for 문을 통해 학생들의 점수를 배열 arr 에 저장하면서, 평균을 구하기 위한 총점 sum 에 더해줍니다.

  3. 평균을 구하여 average 에 대입해주고, for 문과 if문 을 통해 평균을 넘은 학생 수를 구해줍니다.(avgCount++)

  4. 이제 평균을 넘은 학생 수를 총 학생 수로 나누고 100을 곱하여 비율 ratio 을 구하고 이를 ratioArr에 저장합니다.

  5. count++ 를 사용하여 ratioArr의 인덱스를 하나 늘려주고 필요한 만큼 다시 반복문을 돌리게 합니다.

  6. 평균을 넘는 학생 수를 구하기 위한 변수들을 다시 0으로 초기화합니다.


for(int i = 0 ; i < testCase ; i++)
{
    System.out.println(String.format("%.3f", ratioArr[i]) + "%");
}

이제 개인적으로 이 문제의 학습 포인트라고 생각한 소수점 셋째 자리까지 반올림하여 출력하는 부분입니다.
저는 소수점 출력을 위해 String.format() 을 사용하였습니다.
자바에서 소수점을 출력하는 메소드에는
String.format()Math.round()
이렇게 두 가지 있습니다. 기본적으로 소수점을 출력한다는 공통점이 있지만, 소수점 이후에 0만 있는 경우에는 차이가 있습니다.

예를 들어,
String.format() 으로 40.000을 출력하면 그대로 40.000이 출력되지만,
Math.round() 으로 40.000을 출력하면 그냥 40이 출력됩니다.

문제에서는 소수점 뒤에 0만 있을 때도 그대로 출력하길 원하므로 String.format() 메소드를 사용하여 출력하였습니다.


Epilogue

과거에 작성한 코드를 처음부터 다시 보며 이해하는 것은 굉장히 도움이 되는 것 같습니다. 제가 짠 코드를 시간이 지나고 제가 다시 볼 때도 한 번에 안 읽히는데, 다른 사람이 본다면 어떨지 생각하니 변수나 클래스의 네이밍, 가독성 부분을 더욱더 신경 써야겠다고 다짐하게 됩니다.
읽어주셔서 감사합니다!

코드에 대한 조언은 언제나 환영이며, 오히려 부탁드리겠습니다.

profile
For the 1% inspiration.
post-custom-banner

1개의 댓글

comment-user-thumbnail
2020년 3월 17일

Wuhan technology man.....

답글 달기