[프로그래머스 - Lv2] 당구 연습 (JS)

빛트·2023년 3월 20일
0

ALGORITHM-PROGRAMMERS

목록 보기
4/4

( Level 1에서 Level 2로 변경되었네요)

몇가지 실수로 인해 어렵게 느껴졌던 문제입니다


1. 접근방법

입사각과 반사각이 같고, 벽에 부딪히기 전과 후의 이동거리가 같습니다.

다음과 같이 흰색 공의 위치를 벽을 축으로 대칭이동시켰을 때, 흰색 공이 이동한 거리는 노란 공과 검은 공의 거리와 같을 것이라는 것을 쉽게 상상할 수 있습니다.

2. 문제를 어렵게 느끼게 했던 실수들

문제를 꼼꼼히 읽지 않았다

문제에 '머쓱이는 항상 같은 위치에 공을 놓고 쳐서 리스트에 담긴 위치에 놓인 공을 맞춥니다.' 라는 내용이 있습니다.

그런데도 각 수행마다 공의 위치가 변하는 것으로 생각했습니다. 머쓱합니다...

그래서 처음에는 balls.map 이 아니라 balls.reduce 로 방향을 잡고 시작해버렸네요.

네 코너에 인접한 경우의 수를 생각했다

문제에 다음과 같이 공이 코너에 맞는 경우 어떻게 진행되는지에 대해 설명하기 위한 그림이 있습니다.

하지만 애초에 코너에 맞는 경우를 생각할 필요가 없습니다.

잘 생각해보면, 코너에 맞고 나오는 거리보다 가까운 경우가 항상 존재함을 알 수 있습니다.

코드를 더 더 줄이고 싶었다

각 네 면에 대해서 각각 조건문을 달지 않고 싶었습니다만, 위 두가지 실수까지 겹치며 너무 오랜 시간이 흘러서 패스!

3. 코드

각 수행마다 최소 이동거리를 계산하여 배열로 반환합니다

function solution(m, n, startX, startY, balls) {
    return balls.map(([x, y]) => {
        return getNearlist(m, n, startX, startY, x, y);
    });
}

(StartX, StartY)를 네 벽에 대칭이동시켜 목적구와의 거리를 계산합니다.

이 때 대칭이동을 하려는 좌표와의 연장선상에 목적구가 있을 경우에는 거리를 계산하지 않습니다.

이렇게 계산한 거리들의 최솟값을 반환합니다.


const getNearlist = (m, n, x1, y1, x2, y2) => {
    let symmetryPoints = [];

    if (x1 !== x2 || y1 < y2) {
        const bottom = [x1, -y1];
        symmetryPoints.push(bottom);
    }
    if (x1 !== x2 || y1 > y2) {
        const top = [x1, n + n - y1];
        symmetryPoints.push(top);
    }
    if (y1 !== y2 || x1 < x2) {
        const left = [-x1, y1];
        symmetryPoints.push(left);
    }
    if (y1 !== y2 || x1 > x2) {
        const right = [m + m - x1, y1];
        symmetryPoints.push(right);
    }
    
    return symmetryPoints.reduce((min, [x,y])=>{
        return Math.min(min, (x-x2)**2 + (y-y2)**2);
    }, m**2 + n**2);
}

0개의 댓글