코딩가딩가

[JAVA]BOJ 13223

Noooodle 2024. 1. 10. 14:49

문제

나는 이 문제를.. AtoI응용이라고 생각했다. 그래서 String의 숫자를 int로 바꾸고, 두자리씩 끊어서 계산을 했다.

1. String을 int로 바꾸기

    ex) 20:00:00 -> 200000

2. 2자리씩 끊어서 뺄셈

    2-1. int로 바꾼 시작시간이 끝나는 시간보다 크거나 같은 경우 끝나는 시간에 240000을 더해준다.

        ex) start: 20:00:00, end: 04:00:00 -> intStart: 200000, intEnd: 40000 -> intStart가 intEnd보다 큼 -> intEnd+=240000,         intEnd는 280000이 됨

    2-2. 초/분/시 순으로 나눠서 뺄셈을 한다. 시작값이 끝나는 값보다 큰 경우, 끝나는 값에 60을 더해주고 flag를 1로 만들

    어준다. flag는 앞자리에서 하나 내림했다는 표시이다. (2-1.에서 끝나는 값이 더 작은 경우 240000를 더했기 때문에 시

    는 항상 끝나는 값이 더 크다. 그러므로 초와 분에서만 내림이 발생한다.)

    2-3. 이렇게 초/분/시 순으로 구한 값을 8자리(혹은7자리)의 정수가 될 수 있도록 자리수에 가중치를 곱해서 더해준다.

3. 만들어진 차이 정수값을 다시 String으로 만들어준다.

+설명이 난해한 것 같아서 패드에 필기한것 추가. 근데 이것도 난해해 보인다.....

import java.util.Scanner;

public class BOJ13223 {
    public static int AtoI(String str){ // String을 int로 변환
        int i = 0, num = 0;
        char ch;
        while(i<str.length()){
            ch = str.charAt(i);
            if(ch>='0'&&ch<='9'){
                num = num*10 + (ch - '0');
            }
            i++;
        }
        return num;
    }
    public static int calcTime(int sTime, int eTime){ // 초/분/시 순으로 차이를 계산
        int result = 0, s, e, i, flag = 0, comma = 1;

        if(eTime <= sTime) // 끝나는 시간이 더 작은경우
            eTime += 240000;

        for(i=0;i<3;i++){ //
            // 두자리씩 비교, for문을 돌면서 초/분/시 를 각각 계산한다.
            s = sTime % 100;
            sTime = sTime / 100;
            e = eTime % 100;
            eTime = eTime / 100;
            
            if(flag == 1){
                e -= 1;
                flag = 0;
            }
            
            if(s > e){
                e += 60;
                flag = 1;
            }
            
            result += (e - s) * comma; // 8(혹은7)자리가 되도록 가중치를 곱해서 합해줌
            comma *= 100;
        }
        return result;
    }
    public static String addZero(String str){ // String 변환시 0더해줌
        if(str.length() == 1)
            str = "0"+ str;
        return str;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String start, end, result, hh, mm, ss;
        int sTime, eTime, value;

        start = sc.next();
        end = sc.next();

        sTime = AtoI(start);
        eTime = AtoI(end);
        value = calcTime(sTime, eTime);

	// String으로 바꾸기
        ss = (value % 100) + "";
        mm = ((value % 10000)/100) + "";
        hh = (value/10000) + "";

	// String으로 바꾸는 과정에서 한 자리수인 경우, 앞의 0이 사라지므로 더해줘야함
        ss = addZero(ss);
        mm = addZero(mm);
        hh = addZero(hh);

        result = hh + ":" + mm + ":" + ss;
        System.out.println(result);
    }
}

addZero함수는 int를 String으로 만드는 과정에서 사라지는 0을 더해주는 함수이다. 예를 들면 정답이 "04:00:00" 인 경우, 내 코드에서 calcTime으로 반환된 value의 값은 40000이다. 나머지연산과 나누기 연산을 하면 ss = "0", mm = "0", hh = "4"가 될것이다. 이 값을 바로 String으로 만들면 "4:0:0"이 될것이다. 그래서 String이 한 글자인 경우에 앞에 "0"을 더해주는 함수인 addZero를 만들었다. 이렇게하면 "04:00:00" 이라고 나온다. 정답이 "12:34:56"이고  value가 123456인 경우에는 ss = "56", mm = "34", hh = "12" 가 되므로 addZero에서 별 다른 연산없이 바로 리턴될 것이다.


또 다른 방법(1.13 추가)

원리는 같다. 다만 String을 통으로 int로 만들지 않고 시, 분, 초를 나눠서 int로 만들었다. 예를들면 "12:34:56"이면 hh = 24, mm = 34, ss = 56 즉, 두자리 숫자로 만들고 계산했다. 자세한 내용은 코드에 주석으로 적어놓았다.

public static void main(String[] args) {
    String start, end;
    int sHour, sMinute, sSecond, eHour, eMinute, eSecond;
    Scanner sc = new Scanner(System.in);
    start = sc.next();
    end = sc.next();

    // 1. ':'를 기준으로 시간, 분, 초를 쪼개기
    // 1-1) 시,분,초가 정해져있으므로 직관적으로 계산
    /*sHour = (start.charAt(0) - '0') * 10 + (start.charAt(1) - '0');
    sMinute = (start.charAt(3) - '0') * 10 + (start.charAt(4) - '0');
    sSecond = (start.charAt(6) - '0') * 10 + (start.charAt(7) - '0');
    eHour = (end.charAt(0) - '0') * 10 + (end.charAt(1) - '0');
    eMinute = (end.charAt(3) - '0') * 10 + (end.charAt(4) - '0');
    eSecond = (end.charAt(6) - '0') * 10 + (end.charAt(7) - '0');*/

    // 1-2) substring 이용, 결과가 string이므로 int로 변환해준다.
    /*sHour = Integer.parseInt(start.substring(0,2));
    sMinute = Integer.parseInt(start.substring(3,5));
    sSecond = Integer.parseInt(start.substring(6,8));
    eHour = Integer.parseInt(end.substring(0,2));
    eMinute = Integer.parseInt(end.substring(3,5));
    eSecond = Integer.parseInt(end.substring(6,8));*/

    // 1-3) split 이용, 마찬가지로 int로 변환
    String[] sTime = start.split(":");
    String[] eTime = end.split(":");
    sHour = Integer.parseInt(sTime[0]);
    sMinute = Integer.parseInt(sTime[1]);
    sSecond = Integer.parseInt(sTime[2]);
    eHour = Integer.parseInt(eTime[0]);
    eMinute = Integer.parseInt(eTime[1]);
    eSecond = Integer.parseInt(eTime[2]);

    // 2. 시간, 분, 초의 차이를 계산
    // 2-1) 각각 뺄셈하고 음수인 경우에 더 큰 단위에서 내림한다.
    /*int needSecond, needMinute, needHour;
    needSecond = eSecond - sSecond;
    needMinute = eMinute - sMinute;
    needHour = eHour - sHour;

    if(needSecond < 0) {
        needSecond += 60;
        needMinute--;
    }
    if(needMinute < 0) {
        needMinute += 60;
        needHour--;
    }
    if(needHour <= 0)
        needHour += 24;*/

    // 2-2) 작은 단위(초)로 바꾸고 한 번에 계산
    int sSecondAmount = sHour * 3600 + sMinute * 60 + sSecond;
    int eSecondAmount = eHour * 3600 + eMinute * 60 + eSecond;
    int needSecondAmount = eSecondAmount - sSecondAmount;
    if(needSecondAmount <= 0)
        needSecondAmount += 24*3600;

    needHour = needSecondAmount / 3600;
    needMinute = (needSecondAmount % 3600) / 60;
    needSecond = needSecondAmount % 60;

    // 3. 출력하기
    System.out.printf("%02d:%02d:%02d", needHour, needMinute, needSecond);

}

'코딩가딩가' 카테고리의 다른 글

[JAVA]배열  (1) 2024.03.23
[JAVA]BOJ 10158  (1) 2024.01.16
[JAVA]BOJ 1543  (0) 2024.01.04
[JAVA]BOJ 1157  (0) 2024.01.02
[JAVA]BOJ 1919  (0) 2024.01.01