알고리즘

[이코테 with Java] 시각(구현)

크딩학생 2024. 1. 19. 09:31

문제 

정수 N이 입력되면 00시 00분 00초부터 N시 59분 59초까지의 모든 시각 중에서 3이 하나라도 포함되는 모든 경우의 수를 구하는 프로그램을 작성하시오. 예를 들어 1을 입력했을 때 다음은 3이 하나라도 포함되어 있으므로 세어야 하는 시각이다.

  • 00시 00분 03초
  • 00시 13분 30초

반면에 다음은 3이 하나도 포함되어 있지 않으므로 세면 안 되는 시각이다.

  • 00시 02분 55초
  • 01시 27분 45초

입력 조건

  • 첫째 줄에 정수 N이 입력된다. (0 <= N <= 23)

출력 조건

  • 00시 00분 00초부터 N시 59분 59초까지의 모든 시각 중에서 3이 하나라도 포함되는 모든 경우의 수를 출력한다. 

ex) 입력이 5이면, 출력은 11475이다.

 


1. 내가 푼 방식

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int count = 0;
        for(int i=0 ; i<=N ; i++){
            for( int j=0; j<60; j++){
                for( int a=0; a<60; a++){
                    if(  String.valueOf(i).contains("3") || String.valueOf(j).contains("3") || String.valueOf(a).contains("3")){
                        count++;
                    }
                }
            }
        }
        System.out.print(count);
    }
}

 

나는 String 클래스의 valueOf 메서드contains 메서드를 활용해 문제를 풀었다.

0시 00분 00초부터, N시 59분 59초까지 순회하며, 3이 포함되어 있는 경우 count를 +1 시켜주었다.

i, j, a는 모두 int이기 때문에 String.valueOf(int i)를 활용해 String 타입으로 바꿔주었고,

String.contains(String s)를 활용해 해당 문자열 안에 특정 문자열(3)이 포함되어 있는지 여부를 알려주었다. 

 

2. 동빈님이 푼 방식

import java.util.*;

public class Main {

    // 특정한 시각 안에 '3'이 포함되어 있는지의 여부
    public static boolean check(int h, int m, int s) {
        if (h % 10 == 3 || m / 10 == 3 || m % 10 == 3 || s / 10 == 3 || s % 10 == 3)
            return true;
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // H를 입력받기 
        int h = sc.nextInt();
        int cnt = 0;

        for (int i = 0; i <= h; i++) {
            for (int j = 0; j < 60; j++) {
                for (int k = 0; k < 60; k++) {
                    // 매 시각 안에 '3'이 포함되어 있다면 카운트 증가
                    if (check(i, j, k)) cnt++;
                }
            }
        }

        System.out.println(cnt);
    }

}

 

동빈님은 특정 문자열 안에 3이 있는지를 판단하지 않고,

나눗셈을 하여 특정 숫자 안에 3이 포함되어 있는지를 판단했다.

 

이때 static 메서드를 호출해주었는데, 여기서 static을 왜 붙여야 하는지 알아보겠다.

static 메서드는 메모리에 고정적으로 할당되어 값이 변하지 않으면서,

객체 생성 없이 사용할 수 있다.

 

현재 우리는 Main 클래스를 이용하고 있기 때문에 만약 check라는 메서드가 static이 아닐 경우,

Main main = new Main()을 호출해서 사용해야 한다. 

하지만, static이 붙었기 때문에 객체 생성 없이 check(i, j, k)로 호출할 수 있는 것이다. 

 

 

다시 동빈님이 푼 방식을 설명해보겠다. 

동빈님은 0시 00분 00초부터 h시 59분 59초까지 순회하며 check(i, j, k) 함수를 호출하고, 

해당 값이 true이면 cnt++, false이면 cnt 값에 변동을 주지 않았다.

 

여기서 check 함수는 숫자에 "3"이 포함되어 있는지 여부를 알려주는 함수이다.

우리가 생각했을 때 3이 있는 경우는 어떤 경우인가?

 

우선 "시"부터 생각해보면, 0-24이기 때문에 앞자리에 3이 들어갈 일은 없다.

그렇다면, 03, 13, 23처럼 끝자리에 3이 있는 경우가 있다.

끝자리 3인 숫자만 찾아내려면  10으로 나눴을 때 나머지가 3인 숫자만 알아내면 된다. 

3 % 10은 3, 13 % 10도 3, 23 % 10도 3이다.

 

그렇다면 "분"과 "초"는 어떨까?

"분"과 "초"는 00-59까지라서 앞자리에 3이 들어갈 수도 있고, 뒷자리에 3이 들어갈 수도 있다.

끝자리에 3이 들어갈 때는 10으로 나눈 나머지가 3이면 되는데, 앞자리에 3이 들어가는 경우는 어떻게 알아낼까?

바로 10으로 나눈 몫이 3인 경우를 출력하면 된다. 

앞자리에 3이 들어가는 경우는 숫자가 30대인 경우밖에 없다. 

30을 10으로 나누면 몫이 3이기 때문에 이 경우만 알아내면 된다.