[Programmers] 10주차 - 교점에 별 만들기

개발자·2021년 10월 13일
0
post-thumbnail

문제 설명

Ax + By + C = 0으로 표현할 수 있는 n개의 직선이 주어질 때, 이 직선의 교점 중 정수 좌표에 별을 그리려 합니다.

예를 들어, 다음과 같은 직선 5개를

  • 2x - y + 4 = 0
  • -2x - y + 4 = 0
  • -y + 1 = 0
  • 5x - 8y - 12 = 0
  • 5x + 8y + 12 = 0

좌표 평면 위에 그리면 아래 그림과 같습니다.

이때, 모든 교점의 좌표는 (4, 1), (4, -4), (-4, -4), (-4, 1), (0, 4), (1.5, 1.0), (2.1, -0.19), (0, -1.5), (-2.1, -0.19), (-1.5, 1.0)입니다. 이 중 정수로만 표현되는 좌표는 (4, 1), (4, -4), (-4, -4), (-4, 1), (0, 4)입니다.

만약 정수로 표현되는 교점에 별을 그리면 다음과 같습니다.

위의 그림을 문자열로 나타낼 때, 별이 그려진 부분은 *, 빈 공간(격자선이 교차하는 지점)은 .으로 표현하면 다음과 같습니다.

이때 격자판은 무한히 넓으니 모든 별을 포함하는 최소한의 크기만 나타내면 됩니다.

따라서 정답은

입니다.

직선 A, B, C에 대한 정보가 담긴 배열 line이 매개변수로 주어집니다. 이때 모든 별을 포함하는 최소 사각형을 return 하도록 solution 함수를 완성해주세요.

제한사항

  • line의 세로(행) 길이는 2 이상 1,000 이하인 자연수입니다.
    • line의 가로(열) 길이는 3입니다.
    • line의 각 원소는 [A, B, C] 형태입니다.
    • A, B, C는 -100,000 이상 100,000 이하인 정수입니다.
    • 무수히 많은 교점이 생기는 직선 쌍은 주어지지 않습니다.
    • A = 0이면서 B = 0인 경우는 주어지지 않습니다.
  • 정답은 1,000 * 1,000 크기 이내에서 표현됩니다.
  • 별이 한 개 이상 그려지는 입력만 주어집니다.

소스 코드

import java.util.*;

class Node {
    long x;
    long y;
 
    public Node(long x, long y) {
        this.x = x;
        this.y = y;
    }
}

class Solution {
    ArrayList<Node> list = new ArrayList<Node>();
    public static long mx = Long.MIN_VALUE, nx = Long.MAX_VALUE;
    public static long my = Long.MIN_VALUE, ny = Long.MAX_VALUE;
    
    // 교점에 해당되는지 Check
    boolean chkDot(long x, long y){
        for(int i=0;i<list.size();i++){
            if(list.get(i).x == x && list.get(i).y == y) {
                return true;
            }
        }
        return false;
    }
    
    public String[] solution(int[][] line) {
        // 교점 좌표 구하기
        for(int i=0;i<line.length-1;i++) {
            for(int j=i+1;j<line.length;j++) {
            	long A = line[i][0], B = line[i][1], E = line[i][2];
                long C = line[j][0], D = line[j][1], F = line[j][2];
                if(A*D-B*C == 0) 
                    break;
                double x = (double) (B*F-E*D) / (A*D-B*C);
                double y = (double) (E*C-A*F) / (A*D-B*C);
                // 교점 좌표가 정수인지 Check
                if(x == (long) x && y == (long) y) {
                    // x,y 최소/최대값 구하기 
                    mx = Math.max(mx, (long)x);
                    my = Math.max(my, (long)y);
                    nx = Math.min(nx, (long)x);
                    ny = Math.min(ny, (long)y);
                    list.add(new Node((long)x,(long)y));
                }
            }
        }
        
        String[] answer = new String[(int)(my-ny+1)];
        int idx = 0; // answer index
        for(long i=my;i>=ny;i--) { // y는 최대->최소
            String s = "";
            for(long j=nx;j<=mx;j++) { // x는 최소->최대
                // 교점에 해당하면 "*"
                if(chkDot(j,i)) {
                    s += "*";
                    continue;
                }
                // 해당하지 않으면 "."
                s += ".";
            }
            answer[idx] = s;
            idx++;
        }
        return answer;
    }
}

풀이

처음에 교점에 해당되면 *를 표시하기 위해 list를 정렬한 후 차례대로 비교하려고 했더니 오류가 발생했다.. 단순히 for문을 돌려 체크하면 되는 문제였다 😥
위 문제를 해결했더니 케이스 29 오류가 났다.
결국 다른 사람이 질문한 내용을 찾아봤더니 오버플로우가 발생하는 것을 막기위해 A~F를 long형으로 선언해줘야했다.
어떻게 겨우겨우 풀긴 했는데 아직 더 열심히 해야겠다 😫 🧐

profile
log.info("공부 기록 블로9")

0개의 댓글