본문 바로가기

2022-winter-mogakko

2022-모각코 6차시 활동 계획 및 결과

[계획]

1. 백준 실버5 이상 문제 1문제 풀기.

2. 5차시 활동 때 막혔던 문제 공부하기.

    - 별찍기 과정에서 BufferedReader를 사용해 입력받았을 때 원하는대로 안찍히는지 (코드문제?)

    - '공사장 표지판' 문제에서 내가 처음 짠 코드가 어느부분이 잘못되었는지 (출력형식과 맞지 않음.)


[회고]

오늘은 백준 1문제와 5차시 활동을 하면서 궁금했던 점들을 공부했다.

1. 실버5 : 좌표 정렬하기 (11650번)

    문제 : https://www.acmicpc.net/problem/11650

 

11650번: 좌표 정렬하기

첫째 줄에 점의 개수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개의 줄에는 i번점의 위치 xi와 yi가 주어진다. (-100,000 ≤ xi, yi ≤ 100,000) 좌표는 항상 정수이고, 위치가 같은 두 점은 없다.

www.acmicpc.net

이 문제는 람다식을 사용해 sort하는 방법으로 풀었다.

람다식을 사용할 줄 안다면 이 문제는 쉽게 풀리는 문제였다. (물론 나는 몰라서 찾아봤다...ㅎㅎ)

아래는 내가 작성한 코드다.

 

package silver5;
import java.util.*;

public class point_sort_11650_0127 {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt(); // 입력받는 줄수
        sc.nextLine();
        int[][] data = new int[N][2];
        int[] temp = new int[2];

        for(int i = 0; i < N; i++){
            String[] str = sc.nextLine().split(" ");
            data[i][0] = Integer.parseInt(str[0]);
            data[i][1] = Integer.parseInt(str[1]);
        }

        Arrays.sort(data, (t1, t2) -> { // y좌표 정렬
            if(t1[0] == t2[0]){
                return t1[1] - t2[1];
            }
            else {
                return t1[0] - t2[0];
            }
        });

        for(int i = 0; i < N; i++){
            System.out.println(data[i][0] + " " + data[i][1]);
        }

        sc.close();
    }
}

 

입력을 받아 2차원배열에 넣어주었다.

그 후 값이 저장되어 있는 2차원배열을 조건에 맞춰 정렬하면 되는 문제였는데 2차원 정렬을 한번도 해본 적 없어 찾아보았다.

Arrays.sort에 있는 Comparator를 조건에 맞게 작성해주면 되었다. 

그래서 문제에 제시된 대로 x좌표를 오름차순으로 정렬한 뒤 x좌표가 같다면 y좌표를 오름차순으로 정렬하도록 코드를 작성해주었다. 아래는 람다식이 아닌 Comparator를 사용한 코드이다.

 

Arrays.sort(data, new Comparator<int[]>() {
    @Override
    public int compare(int[] t1, int[] t2) {
        if(t1[0] == t2[0]){
            return t1[1] - t2[1];
        }
        else {
            return t1[0] - t2[0];
        }
    }
});

 

이렇게 코드를 작성했을 때 new Comparator부분에 노란색 전구가 떠서 확인해 본 결과 'Replace with Rambda' 즉, 람다식으로 바꿔보라고 조언을 해주었다. 그래서 클릭해봤더니

 

Arrays.sort(data, (t1, t2) -> {
    if(t1[0] == t2[0]){
        return t1[1] - t2[1];
    }
    else {
        return t1[0] - t2[0];
    }
});

 

이런식으로 람다식으로 바뀌면서 매우 간단해졌다.

이 람다식으로 정렬을 해준 뒤 출력을 해주면 문제가 해결된다.

람다식을 잘 몰랐지만 오늘 '좌표 정렬하기' 문제를 풀면서 이해가 되었다.


- BufferedReader로 별찍기

public class test_everything {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        int N = Integer.parseInt(br.readLine());
        System.out.println(N);

        for(int i = 1; i <= N; i++){
            for(int j = 0; j < N-i; j++){
                System.out.print(" ");
            }
            for(int k = 0; k < i; k++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

 

BufferedReader로 입력을 받아 Integer.parseInt()을 사용해 String타입을 Int형으로 바꿔 별찍기를 했을 때 아래와 같이 정상적으로 출력이 되는 것을 볼 수 있다.

br.readLine() 입력

 

public class test_everything {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        Scanner sc = new Scanner(System.in);
        int N = br.read();
        System.out.println(N);

        for(int i = 1; i <= N; i++){
            for(int j = 0; j < N-i; j++){
                System.out.print(" ");
            }
            for(int k = 0; k < i; k++){
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

 

하지만 위의 코드처럼 BufferedReader로 입력받아 br.read()로 입력받아 별을 찍어보면 아래와 같은 결과가 나오게 된다.

br.read() 입력

그래서 차이점을 알아보게 되었다.

- readLine() : Scanner에서 nextLine()처럼 한줄을 통째로 입력받는 방식. String값으로 읽어옴.
- read() : 값을 읽어올 때 int값으로 변형해서 읽어오는 방식. 
=>  만약 1을 read()를 통해 읽어온다면 ASCII형식의 문자값 '1'을 읽어오게 되고, 결국 최종적으로 '1'의 int형값인 49를 읽어오게 된다.

ASCII코드는 다음을 참조 : https://ko.wikipedia.org/wiki/ASCII

 

ASCII - 위키백과, 우리 모두의 백과사전

1972 프린터 사용 설명서에 개시된 아스키 코드 차트표 미국정보교환표준부호(영어: American Standard Code for Information Interchange), 또는 줄여서 ASCII( , 아스키)는 영문 알파벳을 사용하는 대표적인 문자

ko.wikipedia.org

 

BufferedReader에서 사용되는 readLine()과 read()의 차이가 있었다. 나는 이것을 모르고 계속 사용해 원하는 값이 나오지 않았다.

BufferedReader로 수를 입력받을 때 readLine()을 사용한다면 Integer.parseInt(br.readLind()) 방법을 사용하면 되고, read()를 사용하고 싶다면 br.read() - '0' 을 사용하면 된다.

 

※ 결론!

BufferedReader 이기 때문에 원하는 갯수만큼 안찍힌 것이 아니라 read()를 사용할 때 ASCII의 값을 가져온다는 것을 모르고 사용했기 때문에 원하는 모양이 나오지 않았던 것이다.

 

 


 - '공사장 표지판' 문제에서 내가 처음 짠 코드가 어느부분이 잘못되어서 출력형식과 맞지 않는지 아직도 잘 모르겠다...