나를 기록하다
article thumbnail
반응형

백준(baekjoon) 1485 정사각형

https://www.acmicpc.net/problem/1485

 

1485번: 정사각형

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 네 줄로 이루어져 있으며, 점의 좌표가 한 줄에 하나씩 주어진다. 점의 좌표는 -100,000보다 크거나 같고, 100,000보다 작거나 같

www.acmicpc.net

문제

네 점이 주어졌을 때, 네 점을 이용해 정사각형을 만들 수 있는지 없는지를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 네 줄로 이루어져 있으며, 점의 좌표가 한 줄에 하나씩 주어진다. 점의 좌표는 -100,000보다 크거나 같고, 100,000보다 작거나 같은 정수이다. 같은 점이 두 번 이상 주어지지 않는다.

출력

각 테스트 케이스마다 입력으로 주어진 네 점을 이용해서 정사각형을 만들 수 있으면 1을, 없으면 0을 출력한다.

 

문제풀이

이번 문제는 로직을 짜서 정답을 맞추는데는 성공했다. 하지만 나의 첫 풀이에서 볼 수 있듯이, 코드가 매우 난잡하고, 자바의 장점인 객체 지향성을 전혀 살리지 못했다. 그저 돌아가기만 하는 코드다. 아직까지 객체지향적인 사고가 많이 부족한 듯하다.

우선 문제를 풀기 전에 어떻게 풀 지 정리를 했다.

내가 세운 정사각형의 규칙은 다음과 같다.

1. 네 변의 길이가 같을 것
2. 두 변이 이루는 각이 직각일 것

이런 규칙을 만족시키기 위해 다음과 같이 진행했다.

1. Point 클래스를 구현하여 입력받은 좌표 저장 
2. ArrayList<Point> pointList 구현
3. Comparator를 상속받은 PointComparator을 구현하여 x좌표 내림차순, y좌표 내림차순 정렬
4. 각 점의 좌표 추출 후, 점 간의 거리 제곱을 계산(powD01, powD02 ...)
5. isRectangle의 boolean형을 선언하여 직사각형인지 확인(대각선의 제곱 = 나머지 두 변의 각각의 제곱 합이 true인지 확인)
6. isRectangle = true이고, 4번에서 구한 네 변의 길이가 같으면 1을 출력, 아닐 경우 0을 출력
7. 다음 테스트 케이스를 위해 pointList 초기화

첫번째 풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int testCaseCount = Integer.parseInt(reader.readLine()); // 테스트 케이스 진행 횟수

        ArrayList<Point> pointsList = new ArrayList<>(); // points 리스트를 반복문 밖에서 선언

        for (int i = 0; i < testCaseCount; i++) {
            // 한 테스트 케이스마다 4개의 점 정보 입력
            for (int j = 0; j < 4; j++) {
                StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
                int x = Integer.parseInt(tokenizer.nextToken());
                int y = Integer.parseInt(tokenizer.nextToken());
                pointsList.add(new Point(x, y));
            }

            pointsList.sort(new PointComparator()); // 정렬 기준을 활용하여 내림차순 정렬

            // 각 점의 좌표 추출
            int x0 = pointsList.get(0).x;
            int x1 = pointsList.get(1).x;
            int x2 = pointsList.get(2).x;
            int x3 = pointsList.get(3).x;

            int y0 = pointsList.get(0).y;
            int y1 = pointsList.get(1).y;
            int y2 = pointsList.get(2).y;
            int y3 = pointsList.get(3).y;

            // 점 간의 거리 제곱 계산
            int powD01 = (int) (Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
            int powD02 = (int) (Math.pow(x0 - x2, 2) + Math.pow(y0 - y2, 2));
            int powD13 = (int) (Math.pow(x1 - x3, 2) + Math.pow(y1 - y3, 2));
            int powD23 = (int) (Math.pow(x2 - x3, 2) + Math.pow(y2 - y3, 2));
            int powD12 = (int) (Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));

            // 직사각형 여부 판단
            boolean isRectangle = powD12 == powD01 + powD02;

            // 직사각형이면서 네 변의 길이가 모두 같은지 검사
            if (isRectangle && (powD01 == powD02) && (powD02 == powD13) && (powD13 == powD23)) {
                System.out.println(1); // 직사각형이면서 네 변의 길이가 모두 같을 경우
            } else {
                System.out.println(0); // 직사각형이 아닐 경우
            }

            pointsList.clear(); // 다음 테스트 케이스를 위해 리스트 초기화
        }
    }

    // 좌표를 저장하는 클래스
    private static class Point {
        int x, y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    // 점을 내림차순으로 정렬하기 위한 Comparator 구현
    private static class PointComparator implements Comparator<Point> {
        @Override
        public int compare(Point p1, Point p2) {
            if (p1.x != p2.x) {
                return p2.x - p1.x;
            } else {
                return p2.y - p1.y;
            }
        }
    }
}

 

두번째 풀이

두번째 풀이는 다른 사람들의 코드를 보면서 참고하다가 가장 객체지향적인 코드를 조금만 다듬어서 올렸다. 자바를 사용할 때는 이렇게 객체지향적으로 생각하고 코드를 작성해야겠다는 것을 다시 한 번 느낄 수 있는 코드였다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) throws IOException {
        new Main().solve();
    }

    // 좌표를 나타내는 클래스
    class Position {
        int x, y;

        // 좌표 생성자
        public Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    // 두 좌표 사이의 거리 계산 메서드
    private long calculateDistance(Position p1, Position p2) {
        return 1L * (p1.x - p2.x) * (p1.x - p2.x) + 1L * (p1.y - p2.y) * (p1.y - p2.y);
    }

    private void solve() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int testCaseCount = Integer.parseInt(br.readLine()); // 테스트 케이스 개수 입력

        StringBuilder sb = new StringBuilder();

        // 각 테스트 케이스에 대하여 반복
        while (testCaseCount-- > 0) {
            Position[] positions = new Position[4]; // 4개의 좌표를 저장할 배열 생성

            // 4개의 좌표 정보 입력
            for (int i = 0; i < 4; i++) {
                String[] input = br.readLine().split(" ");
                positions[i] = new Position(Integer.parseInt(input[0]), Integer.parseInt(input[1]));
            }

            long[] distances = new long[6]; // 거리를 저장할 배열 생성
            int idx = 0;

            // 모든 좌표 쌍에 대해 거리 계산 후 배열에 저장
            for (int i = 0; i < 4; i++) {
                for (int j = i + 1; j < 4; j++) {
                    distances[idx++] = calculateDistance(positions[i], positions[j]);
                }
            }

            Arrays.sort(distances); // 거리 배열을 오름차순으로 정렬

            // 모든 거리가 같은 경우 직사각형이므로 1, 아닌 경우 0을 결과에 추가
            if (distances[0] == distances[1] && distances[1] == distances[2] &&
                distances[2] == distances[3] && distances[4] == distances[5]) {
                sb.append(1);
            } else {
                sb.append(0);
            }
            sb.append('\n'); // 개행문자 추가
        }

        br.close(); // 입력 스트림 닫기
        System.out.print(sb); // 결과 출력
    }
}

두번째 코드 출처

https://github.com/nahwasa/BOJ_BaekjoonOnlineJudge/blob/master/01400/BOJ_1485.java

 

반응형
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...