혼자 풀어보려고 하다가 결국 시간 더쓰면 안 될듯 해서 (수학적 개념이 분명 있을 거라고 생각했기에..) 질문하기 페이지를 보았는데 힌트가 있었다
힌트를 참고하여 왼쪽, 오른쪽, 아래쪽, 위쪽에 부딪치는 4가지 경우의 수를 고려해 target좌표의 점대칭 좌표를 구하고, 각 좌표마다의 최소거리 중 최솟값을 정답 배열에 담고자 했다
또한 문제에도 나와 있듯이 머쓱이는 쿠션(공을 쳐서 벽에 맞히는 것)을 원했기에 주어진 예시 케이스처럼 벽에 부딪치지 않는 경우를 고려해야 했다 그래서 상하와 좌우를 세트로 묶어 두 가지 조건으로 나누어 코드를 쓰면 짜잔~ 하고 될 줄 알았으나..
- start ball과 target ball의 x좌표가 동일하면 상, 하 모두를 배제
- start ball과 target ball의 y좌표가 동일하면 좌, 우 모두를 배제
처음에는 이렇게 접근을 했는데 어라? 실패가 많길래 또 질문하기 참고.. 똑똑하신 분이 친절하게 히든 테스트 케이스와 함께 힌트를 제공해주셨기에 감사한 마음으로 적용했다
직관적으로는 이상하지만 일자로 겹쳐 있는 볼을 아예 칠 수 없다는 조건이 없으니 어쨌든 직선으로 원쿠션이 걸리는 조건을 고려해야 했다
따라서 x좌표가 동일할 때는 start ball의 y좌표 값이 target ball보다 작냐 크냐에 따라 상/하 중에 하나는 최솟값 계산에 포함을 시켰다
(y좌표가 동일할 때도 같은 논리로 좌/우 중에 하나는 포함)
x좌표 동일할 때 예시
- startY > targetY : 내가 쳐야 하는 공이 더 위에 있으니 up 벽에는 부딪칠 수 있다
- startY < targetY : 내가 쳐야 하는 공이 더 아래에 있으니 down 벽에는 부딪칠 수 있다
그 결과 다행히도 통과
function solution(m, n, startX, startY, balls) {
return balls.reduce((answer, ball) => {
const [targetX, targetY] = ball;
const targetMaps = {
left: [-targetX, targetY],
down: [targetX, -targetY],
right: [m + (m - targetX), targetY],
up: [targetX, n + (n - targetY)],
};
const targetVals = {
left: (startX - targetMaps["left"][0]) ** 2 + (startY - targetMaps["left"][1]) ** 2,
down: (startX - targetMaps["down"][0]) ** 2 + (startY - targetMaps["down"][1]) ** 2,
right: (startX - targetMaps["right"][0]) ** 2 + (startY - targetMaps["right"][1]) ** 2,
up: (startX - targetMaps["up"][0]) ** 2 + (startY - targetMaps["up"][1]) ** 2,
};
// x축 좌표 동일 - U or D 배제
if (startX === targetX) {
if (startY < targetY) return [ ...answer, Math.min(targetVals["left"], targetVals["right"], targetVals["down"])];
if (startY > targetY) return [ ...answer, Math.min(targetVals["left"], targetVals["right"], targetVals["up"])];
}
// y축 좌표 동일 - L or R 배제
if (startY === targetY) {
if (startX < targetX) return [ ...answer, Math.min(targetVals["up"], targetVals["down"], targetVals["left"])];
if (startX > targetX) return [ ...answer, Math.min(targetVals["up"], targetVals["down"], targetVals["right"])];
}
return [ ...answer, Math.min(...Object.values(targetVals))];
}, []);
}