https://school.programmers.co.kr/learn/courses/30/lessons/87377
문제설명
이렇게 식이 주어지면 이 함수들을 좌표에 그려본다.
그럼 이 상태가 되고 교점이 5개가 생긴다. 이 교점들 중 (x, y)가 정수인 좌표를 구한다. 이 결과를
이렇게 최소의 크기의 격자판으로 출력한다.
해결 과정
이 문제의 아래 부분을 보면 힌트를 준다.
이렇게 교점이 한개만 생길 때가 언제인지 알려준다. 두 개의 직선 이므로 교점은 하나만 생긴다.
- 만약 AD - BC가 0이라면 교점이 유일하지 않다는 것이고 넘어가면 된다.
- 교점이 생겼다면 x 와 y가 정수인 좌표를 찾으면 된다.
- 그 교점들을 토대로 격자판의 크기를 설정하고 '*'의 위치를 세팅해 준 뒤 출력한다.
전체 코드
import java.util.*;
class Node {
long x; long y;
public Node(long x, long y){
this.x = x; this.y = y;
}
}
class Solution {
public String[] solution(int[][] line) {
// x와 y를 저장할 ArrayList
ArrayList<Node> arr = new ArrayList<>();
long x = 0; long y = 0;
// 최대, 최소 크기 세팅
long max = Long.MAX_VALUE * -1; long may = Long.MAX_VALUE * -1;
long mix = Long.MAX_VALUE; long miy = Long.MAX_VALUE;
for(int i = 0; i < line.length-1; ++i){
for(int j = 1; j < line.length; ++j){
long A = line[i][0]; long B = line[i][1]; long E = line[i][2];
long C = line[j][0]; long D = line[j][1]; long F = line[j][2];
long temp = A*D - B*C;
if(temp == 0) continue;
else {
long tempx = B*F - E*D;
long tempy = E*C - A*F;
double resx = (double) tempx % temp;
double resy = (double) tempy % temp;
// 나머지가 0이 아니면 정수가 아닌 것
if (resx == 0 && resy == 0){
x = tempx / temp;
y = tempy / temp;
max = Math.max(max, x);
mix = Math.min(mix, x);
may = Math.max(may, y);
miy = Math.min(miy, y);
arr.add(new Node(x,y));
}
}
}
}
// 격자점의 크기는 최대 좌표에서 최소 좌표를 뺀 것이다.
int height = (int) (may-miy+1);
int width = (int) (max-mix+1);
char[][] temp_ans = new char[height][width];
for(int i = 0 ; i < height; ++i){
for(int j = 0; j< width; ++j){
temp_ans[i][j] = '.';
}
}
// 교점의 좌표의 기준을 바꿔야 한다.
// 원래는 (0, 0)이지만 (0, 0)이 왼쪽 맨 위로 바뀐다.
// 그러므로 y값 최대 x값 최소가 (0, 0)으로 바뀐다.
for(int i = 0; i < arr.size(); ++i){
temp_ans[(int) (may-arr.get(i).y)][(int) (arr.get(i).x-mix)] = '*';
}
String[] answer = new String[temp_ans.length];
for(int i = 0; i < answer.length; ++i){
answer[i] = new String(temp_ans[i]);
}
return answer;
}
}
잘 짠 코드란?
https://product.kyobobook.co.kr/detail/S000200928002
이번 방학부터 이 책을 사서 공부를 하고 있다. 이 책을 보니 잘 짠 코드란 부분이 나온다.
- 제일 처음 문제를 해결할 수 있어야 한다. 이건 당연한 부분
- 가독성을 높여야 한다. 코드 역할에 집중
- 알맞은 함수 이름과 변수 이름을 설정해야 한다.
- 디버깅과 시행착오 줄이기
- 직접 설계하며 코드 작성해보기
이런 내용들이 있었다.
위의 문제는 이 책에서 추천해 주는 문제였는데 책을 안 보고 혼자 한번 풀어보았다.
풀 수는 있었지만 내 코드는 가독성이 엄청 떨어진다는 것을 알 수 있었다. 제일 큰 문제는 로직을 나만 알아볼 수 있다는 것이다. 지금까지 코딩테스트를 볼 때 어떻게든 풀어만 보자라고 생각했는데 이번 방학부터는 잘 풀어서 내 풀이로 남을 설득해보자로 생각을 바꿔봐야겠다.
이제 이 책에서 설명해준대로 코드를 짜보겠다.
메소드를 만들어서 각각의 로직을 만들어보자
이 문제에는 여러가지 로직들이 나온다.
- 교점 좌표 구하기
- 정수 좌표만 저장
- 저장된 정수들에 대해 x, y 좌표 최댓값 최솟값 구하기
- 2차원 배열 별 표시
크게 이 정도다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class programmers_87377 {
private static class Point{
//데이터를 나타내는 클래스이므로 final 키워드 사용(불병성 가짐)
public final long x, y;
private Point(long x, long y){
this.x = x;
this.y = y;
}
}
// 교차점 구하기
private Point intersection(long a1, long b1, long c1, long a2, long b2, long c2){
double x = (double) (b1*c2 - b2*c1) / (a1*b2 - a2*b1);
double y = (double) (a2*c1 - a1*c2) / (a1*b2 - a2*b1);
if(x % 1 == 0 && y % 1 == 0) return new Point((long) x, (long) y);
return null;
}
//최솟값 구하기
private Point getMinimumPoint(List<Point> points) {
long x = Long.MAX_VALUE;
long y = Long.MAX_VALUE;
for(Point p : points){
x = Math.min(x, p.x);
y = Math.min(y, p.y);
}
return new Point(x,y);
}
//최댓값 구하기
private Point getMaximumPoint(List<Point> points) {
long x = Long.MIN_VALUE;
long y = Long.MIN_VALUE;
for(Point p : points){
x = Math.max(x, p.x);
y = Math.max(y, p.y);
}
return new Point(x,y);
}
public String[] main(int[][] line) {
List<Point> points = new ArrayList<>();
for (int i = 0; i < line.length; i++) {
for (int j = i; j < line.length; j++) {
Point intersection = intersection(line[i][0], line[i][1], line[i][2], line[j][0], line[j][1], line[j][2]);
if(intersection != null){
points.add(intersection);
}
}
}
Point max = getMaximumPoint(points);
Point min = getMinimumPoint(points);
int width = (int) (max.x - min.x + 1);
int height = (int) (max.y - min.y + 1);
// char 1차원 배열 한번에 다채우기
char[][] arr = new char[height][width];
for(char[] row : arr){
Arrays.fill(row, '.');
}
for(Point p : points){
int x = (int) (p.x - min.x);
int y = (int) (max.y - p.y);
arr[y][x] = '*';
}
// char 1 row를 모두 String으로 변경
String[] result = new String[arr.length];
for (int i = 0; i < result.length; i++) {
result[i] = new String(arr[i]);
}
return result;
}
}
'코딩테스트 공부 > 알고리즘 공부' 카테고리의 다른 글
거리두기 확인하기(프로그래머스) JAVA (0) | 2023.06.24 |
---|---|
삼각 달팽이(프로그래머스) JAVA (0) | 2023.06.21 |
입국심사(프로그래머스) JAVA (0) | 2023.05.02 |
여행경로(프로그래머스) JAVA (0) | 2023.04.30 |
모두 0으로 만들기(프로그래머스) JAVA (0) | 2023.03.30 |