https://www.acmicpc.net/problem/1485
문제
네 점이 주어졌을 때, 네 점을 이용해 정사각형을 만들 수 있는지 없는지를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 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
'Algorithm > baekjoon' 카테고리의 다른 글
[백준 3230/자바(java)] 금메달, 은메달, 동메달은 누가? (1) | 2023.09.20 |
---|---|
[백준 1384/자바(java)] 메시지 (0) | 2023.08.24 |
[백준 1002/자바(java)] 터렛 (0) | 2023.08.21 |
[백준 1380/자바(java)] 귀걸이 (0) | 2023.08.20 |
[백준 1343/자바(java)] 폴리오미노 (0) | 2023.08.18 |