프로그래머스 Level 2 당구 연습

2023. 3. 21. 01:22알고리즘/문제

당구 연습

출처 : 프로그래머스

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

 

프로그래머스

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

programmers.co.kr

광고가 없는 비상업적, 비영리적 글입니다.

 

문제 풀이

 

먼저 크게 3개의 영역으로 나누어 풀었습니다.

1. x가 같을 때

2. y가 같을 때

3. x과 y가 둘 다 다를 때

 

1. x가 같을 때

상단 왼쪽 그림 - 좌측 x=0을 기준으로 대칭했을 때 

상단 우측 그림 - 우측 x=m을 기준으로 대칭했을 때

하단 왼쪽 그림 - y1이 y2보다 클 때, y=n의 축을 찍고 내려와서 다른 공에 부딪힐 때 => y = n을 대칭으로 했을 때

하단 오른쪽 그림 - y1이 y2보다 작을 때, y=0의 축을 찍고 올라가서 다른 공에 부딪힐 때 => y = 0을 대칭으로 했을 때

 

이렇게 4가지를 따져야 합니다.

 

 y가 같고 x가 다를 때도 위와 같이 동일합니다.

 

그리고

 

x와 y 좌표가 모두 다를 때는 

1,2,3,4의 번호가 적힌 지점을 축으로 대칭 이동해 각 구해야합니다.

하나 예를 들면

위를 기준으로 대칭하면 아래처럼 삼각형이 나오고 변의 제곱은 (x2-x1)*(x2-x1) + (2n-y1-y2) * (2n-y1-y2) 이렇게 나오게 됩니다. 

 

이제 왼쪽 오른쪽 바닥을 기준으로 대칭이동 후에 길이의 제곱을 구하면 됩니다. 

 

 

왜 모서리로 가는 건 따지지 않을까요???

아래의 그림을 보시면 구석에 가는 공은 무조건 직각 삼각형의 가장 긴 변이 됩니다.

그림을 보시면 이해가 되실겁니다. 그래서 공들이 어떤 곳에 있든지 구석으로 가는 건 먼 길 임을 알 수 있습니다.

코드

두 점 사이의 거리는 거리^2 = x좌표 차^2 + y좌표 차^2 입니다. 값을 구할 때 abs와 sqrt 함수를 사용할 수 있지만 느린 함수입니다.사용하지 않고도 간단하게 구할 수 있으므로 없이 풀었습니다.

class Solution {
    fun solution(m: Int, n: Int, startX: Int, startY: Int, balls: Array<IntArray>): IntArray {
        val answer: IntArray = IntArray(balls.size)
        // 이해를 돕기 위한 x1, y1 변수
        val x1 = startX
        val y1 = startY
        balls.forEachIndexed { index, (x2, y2) ->
            if (x1 == x2) {
            	// x 좌표가 같을 때
                val d1 = (y2 - y1) * (y2 - y1) + 4 * x1 * x1
                val d2 = (y2 - y1) * (y2 - y1) + 4 * (m - x1) * (m - x1)
                // 치는 돌이 맞는 돌보다 밑에 있는지, 위에 있는지에 따라 다릅니다.
                val d3 = if (y1 < y2) (y1 + y2) * (y1 + y2) else (2 * n - y1 - y2) * (2 * n - y1 - y2)
                answer[index] = min(min(d1, d2), d3)
            } else if (y1 == y2) {
            	// y 좌표가 같을 때
                val d1 = (x2 - x1) * (x2 - x1) + 4 * y1 * y1
                val d2 = (x2 - x1) * (x2 - x1) + 4 * (n - y1) * (n - y1)
                // 치는 돌이 맞는 돌의 왼쪽인지 오른쪽인지에 따라 다릅니다.
                val d3 = if (x1 < x2) (x1 + x2) * (x1 + x2) else (2 * m - x1 - x2) * (2 * m - x1 - x2)
                answer[index] = min(min(d1, d2), d3)
            } else {
            	//x, y 좌표 둘 다 다를 때
                //바닥 기준 뒤집기
                val d1 = (x2 - x1) * (x2 - x1) + (y2 + y1) * (y2 + y1)
                // 왼쪽 기준 뒤집기
                val d2 = (x2 + x1) * (x2 + x1) + (y2 - y1) * (y2 - y1)
                // 오른쪽 기준 뒤집기
                val d3 = (y2 - y1) * (y2 - y1) + (2 * m - x1 - x2) * (2 * m - x1 - x2)
                // 위 기준 뒤집기
                val d4 = (x2 - x1) * (x2 - x1) + (2 * n - y1 - y2) * (2 * n - y1 - y2)
                answer[index] = min(min(d1, d2), min(d3, d4))
            }
        }
        return answer
    }
}

결과