본문 바로가기
Algorithm(코딩테스트)/코딩테스트 | 기초 개념 시리즈

[JAVA] 시뮬레이션 1 - 시간 계산 / 날짜 계산 / 진수 변환 / 구간 칠하기 / 사각형 칠하기

by 카랑현석 2024. 12. 6.

요약

간단한 시뮬레이션에 대해 학습한다.

- 시간 계산 (주어진 것 중 가장 작은 단위로 변환하여 풀이)

- 날짜 계산 (주어진 것 중 가장 작은 단위로 변환하여 풀이)

- 진수 변환 (진수 변환 방식 그대로 구현, a 진수 -> b 진수 변환 시 a 진수 -> 10 진수 -> b 진수 로 변환) 

- 구간 칠하기 (1차원 배열 flood fill)

- 사각형 칠하기 (2차원 배열 flood fill)

 

시간 계산 / 날짜 계산

  • 가장 작은 (또는 공통된 단위)로 변환하여 계산한다.

Ex) 시간을 분 단위로 환산하여 계산

Ex) 날짜를 일 단위로 변환하여 계산

 

  • System.out.println() 으로 찍어가면서 코딩하는 것이 정확함.

시간 계산

 

날짜 계산

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

public class Main {
    static int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String input = br.readLine();
        StringTokenizer st = new StringTokenizer(input, " ");
        int m1 = Integer.parseInt(st.nextToken());
        int d1 = Integer.parseInt(st.nextToken());
        int m2 = Integer.parseInt(st.nextToken());
        int d2 = Integer.parseInt(st.nextToken());
        
        // logic //
        int day1 = 0;
        int day2 = 0; 
        for(int i=1; i<=m1-1; i++) {
            day1 += days[i];
        }
        day1 += d1;

        for(int i=1; i<=m2-1; i++) {
            day2 += days[i];
        }
        day2 += d2;

        // output //
        bw.write(String.format("%d", day2-day1+1));
        bw.flush();
        bw.close();
    }
}

 

풀어보면 좋은 문제

코드트리_흐른 날짜 계산 https://www.codetree.ai/missions/5/problems/date-to-date/description #날짜 계산
⭐코드트리_DateTime to DateTime https://www.codetree.ai/missions/5/problems/datetime-to-datetime/description #날짜+시간 계산
⭐ 코드트리_요일 맞추기 https://www.codetree.ai/missions/5/problems/guess-day-of-week/description #날짜 계산
#배열 인덱스 회전 응용
⭐ 코드트리_그 요일은 https://www.codetree.ai/missions/5/problems/the-day-of-the-day/description #날짜 계산

진수 변환 (Notation)

10진수 -> 2진수

 

1) 2를 나눈 나머지를 digits 리스트에 저장하고 ( 언제까지? 2로 나눠서 몫이 안나올 때까지 -> 수가 1 이하일 때 )

2) 그 리스트들을 역순으로 출력한다.

 

// 10진수 -> 2진수

public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int n = Integer.parseInt(br.readLine());

        // logic //
        ArrayList<Integer> digits = new ArrayList<>(); // 결과를 담는 리스트

        while(n > 1) {
            digits.add(n%2);
            n = n / 2;
        }
        digits.add(n);
        
        // output //
        for(int i=digits.size()-1; i >= 0; i--) {
            bw.write(digits.get(i)+"");
        }
        bw.flush();
        bw.close();
    }
}

 


2진수 -> 10진수

 

가중치(weight) 변수를 하나 두고 입력받은 수와 곱해준다.

2진수 -> 10진수

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

public class Main {
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String input = br.readLine();

        // logic // 
        int ans = 0;
        int weight = 1; // 가중치
        for(int i=input.length()-1; i>=0; i--) {
            ans += (input.charAt(i) -'0') * weight;
            weight *= 2;
        }
        
        // output //
        bw.write(ans+"");
        bw.flush();
        bw.close();
    }
}

 

풀어보면 좋은 문제

코드트리_2진수로 변환하기 https://www.codetree.ai/missions/5/problems/convert-to-binary/description #10진수 → 2진수 변환
⭐코드트리_여러가지 진수변환 https://www.codetree.ai/missions/5/problems/various-numeral-system-transformations/description #10진수 → n진수 변환
⭐ 코드트리_진수 to 진수 https://www.codetree.ai/missions/5/problems/transformation-of-number-system/description #a진수 → b진수 변환

 

구간 칠하기

A는 2~5 의 구간을 청소하였고, B는 3~8의 구간을 청소하였다. 총 몇 칸을 청소했는지 구하라.

 

위와 같은 문제는 아래와 같이 1차원 배열의 인덱스를 활용해 시뮬레이션 할 수 있다.

 

최종적으로 배열의 길이만큼 순회하면서 1으로 찍힌 개수를 세면 되는 문제이다.

 

이때 만약 음수가 있다면, 인덱스에는 arr[-10]과 같이 음수의 개념이 없으므로 양수 부분에서 추가로 할당한다.

Ex) 칠하는 범위가 -10~10 인 경우 0~10은 arr[0]~arr[10] 범위에 담고, -1~-10은 arr[11]~arr[20] 범위에 담는다.

어떻게 ? 모든 수에 + 10을 더하면 된다. 그러면 -10은 0 인덱스에 넣게 되고, 10은 20 인덱스에 넣을 수 있게 된다.

 

오답노트

1. 배열 초기화 시 전역 범위에서 초기화하면 int 배열은 0으로 초기화되고, Integer 배열은 null로 초기화된다.

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

public class Main {
    static final int MAX_N = 101;
    public static void main(String[] args) throws IOException {
        int[] board = new int[MAX_N]; // 0으로 초기화
        Integer[] board = new Integer[MAX_N]; // null으로 초기화
        for(int i=0; i<board.length; i++) {
            System.out.println(board[i]);
        }
    }
}

 

따라서, Integer 배열의 경우 아래와 같이 Array.fill 을 사용해서 모든 요소를 0으로 초기화 해주어야 한다.

        Integer[] board = new Integer[MAX_N];
        Arrays.fill(board, 0); // 0으로 초기화

 

풀어보면 좋은 문제

⭐⭐코드트리_왔다 갔던 구역 2 https://www.codetree.ai/missions/5/problems/area-been-to-and-from2/description #구간 칠하기
⭐⭐코드트리_흰검 칠하기 https://www.codetree.ai/missions/5/problems/painting-white-black/description #구간 칠하기 (타일 뒤집기 유형)
⭐⭐코드트리_신기한 타일 뒤집기 https://www.codetree.ai/missions/5/problems/strange-flipping-tiles/description #구간 칠하기 (타일 뒤집기 유형)

 

사각형 칠하기

(1,2)와 (4,3)을 모서리로 하는 직사각형의 넓이를 구하는 문제는 다음과 같이 해결할 수 있다.

  • 아래처럼 2차원 배열을 만들고 그 영역에 해당하면 1로 채워 그 개수를 세면 된다.
  • 항상 인덱스 실수하는 것 조심하기 - System.out.println 으로 찍어가면서 하는 것이 좋음.

 

이렇게 시뮬레이션으로 풀면 겹친 부분의 넓이를 해결하기 수월하다.

 

풀어보면 좋은 문제

코드트리_색종이의 총 넓이 https://www.codetree.ai/missions/5/problems/the-total-area-of-colored-paper/description #겹쳐진 사각형의 넓이 구하기
⭐코드트리_겹치지 않는 사각형의 넓이 https://www.codetree.ai/missions/5/problems/area-of-non-overlapping-rectangle/description #겹쳐진 사각형의 넓이 빼기
⭐⭐코드트리_잔해물을 덮기 위한 사각형의 최소 넓이 https://www.codetree.ai/missions/5/problems/minimum-area-of-rectangle-to-cover-debris/description #겹쳐진 사각형의 넓이 빼기
#예외 처리