프로그래머스 - 10주차_교점에 별 만들기

well-life-gm·2021년 10월 31일
0

프로그래머스

목록 보기
10/125

프로그래머스 - 10주차_교점에 별 만들기

아 처음에 가볍게 풀어본다는 생각으로 시작해서 엣지케이스 때문에 개삽질했다;

일단 얻은 첫 번째 교훈은 문제를 꼼꼼히 읽어봐야한다는 것인데,
그림도 크고 글자도 많아서 대충 읽었다가.

참고사항

다음과 같이 참고사항이 있는 것을 못보고, 교점 구하는 방법을 되게 이상하고 힘들게 하고 있엇다;
수식을 종이에 조금만 적어봐도 금방 알 수 있는 방정식인데, 괜히 막 GCD 구하고...

흔적...

int GCD(int a, int b)
{
    if(a % b == 0)
        return b;
    return GCD(b, a % b);
}

아무튼 저 식을 이용해서 풀다보면 평행하면 어떡하지? 라는 생각이 들 수 있는데,
제한사항

다행히 친절하게 제한해준다.
그래서 그냥 간단하게 풀면 되는데, 여기서 하나 주의할 것은 A, B, C가 -100,000 이상 100,000 이하인 것이다.
100,000은 10의 5승정도인데, 10은 약 2의 3승정도, 즉 100,000은 2의 16승정도로 생각하면 된다.
그러면 A*B를 하면 어떻게 되겠는가. 당연히 Integer Overflow가 발생한다. (이 부분을 제대로 알지 못해서 좀 고생함;)
이 것을 주의해서 자료형을 int가 아니라 long long으로 형변환해서 사용해주면 된다...
파라미터로 주어지는 값도 int이기 때문에 그냥 모든 자료형을 long long으로 사용해주게 좋다.

#include <string>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;
class Pos
{
private:
    long long x;
    long long y;

public:
    Pos(long long a, long long b): 
        x(a), y(b) 
    {}
    
    virtual ~Pos() {}
    
    long long getX() const {
        return x;
    }
    long long getY() const {
        return y;
    }
    bool operator==(const Pos &a) {
        return (this->x == a.x) && (this->y == a.y);
    }    
};

vector<string> solution(vector<vector<int>> line) {
    int size = line.size();
    long long max_x = LLONG_MIN, max_y = LLONG_MIN;
    long long min_x = LLONG_MAX, min_y = LLONG_MAX;
    vector<Pos> result;
    
    for(int i=0;i<size;i++) {
        long long baseX = line[i][0];
        long long baseY = line[i][1];
        long long baseC = line[i][2];
            
        for(int j=i+1; j<size;j++) {
            long long targetX = line[j][0];
            long long targetY = line[j][1];
            long long targetC = line[j][2];

            long long parent = (baseX*targetY*1LL - baseY*targetX*1LL);
            long long Xchild = (baseY*targetC*1LL - baseC*targetY*1LL);
            long long Ychild = (baseC*targetX*1LL - baseX*targetC*1LL);
            if(parent == 0)
                continue;
            if((Xchild % parent) || (Ychild % parent)) 
                continue;
            
            long long result_x, result_y;
            result_x = (long long)Xchild / parent;
            result_y = (long long)Ychild / parent;
            Pos entity = Pos(result_x, result_y);
            if(find(result.begin(), result.end(), entity) == result.end()) {
                result.push_back( {result_x, result_y} );
                max_x = max(result_x, max_x);
                max_y = max(result_y, max_y);
                min_x = min(result_x, min_x);
                min_y = min(result_y, min_y);
            }
        }
    }
    
    // 이 방식이 코드가 깔끔해보임
    string tmp(max_x - min_x + 1, '.');
    vector<string> answer(max_y - min_y + 1, tmp);
    /*vector<string> answer;
    for(long long i=min_y;i<=max_y;i++) {
        string tmp = "";
        for(long long j=min_x;j<=max_x;j++) 
            tmp += ".";
        answer.push_back(tmp);
    }*/
    
    for(int i=0;i<result.size();i++) {
        long long new_x, new_y;
        new_x = abs(min_x - result[i].getX());
        new_y = abs(max_y - result[i].getY());
        answer[new_y][new_x] = '*';
    }
    return answer;
}

이번엔 class를 사용해서 == 연산을 오버로딩했다.
그 이유는 result로 담는 곳에 교점이 다음과 같이 중복적으로 들어갈 수 있는데, ((0,0)만 3개가 들어간다.)
중복 그림

이를 방지하기 위해서 find 함수를 통해서 존재하지 않는 entity만 교점 집합에 포함시켜준다.
이를 위해 (x, y)를 멤버로 갖는 class를 선언하고 == 연산을 다음과 같이 오버로딩했다.

    bool operator==(const Pos &a) {
        return (this->x == a.x) && (this->y == a.y);
    }    

다른 코드를 보니 그냥 2차원 벡터를 쓰면 굳이 class를 선언해서 오버로딩안해도 primitive 자료형의 == operator가 알아서 특정 행 값을 비교해주는 것 같다..
그래도 명시적인 코드를 적은거에 의의를 두면 될 것 같다.

결과는 다음과 같다. 29번의 경우 integer overflow가 발생한 경우고, 이를 double로 해결하려하면 27, 28번에서 메모리초과가 발생한다고 한다.

결과2

profile
내가 보려고 만든 블로그

0개의 댓글