몸과 마음이 건전한 SW 개발자

프로그래머스 [Lv. 2] 당구 연습 {언어 : JavaScript} 본문

알고리즘

프로그래머스 [Lv. 2] 당구 연습 {언어 : JavaScript}

스위태니 2024. 4. 11. 02:01

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/169198

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

정답 코드

function solution(m, n, startX, startY, balls) {
    const answer = [];
        
    const calc = (nx, ny) => {
        return (startX - nx) ** 2 + (startY - ny) ** 2;
    };
    
    const crossFC = (nx, ny) => {
        return nx * n == ny * m || m * ny == n * m - n * nx;
    };
    
    const isCross = crossFC(startX, startY) ? true : false;
    
    balls.forEach(([x, y]) => {
        let minV = 8000001;
        // 대각선에 있는 경우
        if (isCross && crossFC(x, y)) {
            if (x > startX && y > startY) {
                // 우상
                minV = Math.min(minV, (m-x)**2+(n-y)**2+(m-startX)**2+(n-startY)**2);
            } else if (x > startX && y < startY) {
                // 우하
                minV = Math.min(minV, (m-x)**2+y**2+(m-startX)**2+startY**2);
            } else if (x < startX && y > startY) {
                // 좌상
                minV = Math.min(minV, x**2+(n-y)**2+startX**2+(n-startY)**2);
            } else {
                // 좌하
                minV = Math.min(minV, x**2+y**2+startX**2+startY**2);
            };   
        };
        const udlr = [[x, -y], [x, (n-y)*2+y], [-x, y], [(m-x)*2+x, y]];
        if (y == startY) {
            for (let i = 0; i < 2; i++) {
                const [nx, ny] = udlr[i];
                minV = Math.min(minV, calc(nx, ny));
            };
            if (x > startX) {
                minV = Math.min(minV, (x+startX)**2);    
            } else {
                minV = Math.min(minV, (2*m-x-startX)**2);
            };
        } else if (x == startX) {
            for (let j = 2; j < 4; j++) {
                const [nx, ny] = udlr[j];
                minV = Math.min(minV, calc(nx, ny));
            };
            if (y > startY) {
                minV = Math.min(minV, (y+startY)**2);
            } else {
                minV = Math.min(minV, (2*n-y-startY)**2);
            };
        } else {
            for (let k = 0; k < 4; k++) {
                const [nx, ny] = udlr[k];
                minV = Math.min(minV, calc(nx, ny));
            };
        };
        answer.push(minV);
    });
    return answer;
}

풀이 방법

  1. startX, startY가 대각선에 위치하는지 확인한다.
  2. x, y도 대각선에 위치하는지 확인한다.
  3. 대각선에 위치하는 경우
    1. 어떤 모서리에 먼저 닿을지 확인한다.
  4. x나 y가 평행선에 있는지 확인한다.
    1. 평행선인 경우 평행하게 벽을 맞춘 거리 값도 같이 계산한다.
    2. 평행이 아닌 경우 벽 4개를 다 부딪혀본다고 생각한다.
  5. 마지막으로 minV를 answer에 넣는다.

가상의 선을 이어서 그려보면 대칭인 것을 알 수 있다.

느낀점

  • 이건 수학 문제다.