https://school.programmers.co.kr/learn/courses/30/lessons/169198
위의 사진에서 원 쿠션을 통한 (7,7)과 (3,7)의 거리와 (3,7)과 (7, 13)의 거리는 같다.
이 방법을 이용해 문제에 접근한다.
from collections import defaultdict
def solution(m, n, startX, startY, balls):
def is_same(ball, x, y, dir):
while True:
y += dy[dir]
x += dx[dir]
if y <= 0 or y >= n or x <= 0 or x >= m:
return False
if [x, y] == ball:
return True
dy, dx = [1, -1, 0, 0], [0, 0, -1, 1] # U, D, L R
directions = ['U', 'D', 'L', 'R']
answer = []
direction_dict = defaultdict(int)
for i in range(4):
dir = directions[i]
cy, cx = startY, startX
while True:
cy += dy[i]
cx += dx[i]
if cy <= 0 or cy >= n or cx <= 0 or cx >= m:
direction_dict[dir] = (cx, cy)
break
for ball in balls:
feasible = []
for direction in directions:
if direction == 'U' and not is_same(ball, startX, startY, 0):
flip = (ball[0], ball[1] + (direction_dict[direction][1] - ball[1]) * 2)
feasible.append((flip[0] - startX) ** 2 + (flip[1] - startY) ** 2)
elif direction == 'D' and not is_same(ball, startX, startY, 1):
flip = (ball[0], ball[1] + (direction_dict[direction][1] - ball[1]) * 2)
feasible.append((flip[0] - startX) ** 2 + (flip[1] - startY) ** 2)
elif direction == 'L' and not is_same(ball, startX, startY, 2):
flip = (ball[0] + (direction_dict[direction][0] - ball[0]) * 2, ball[1])
feasible.append((flip[0] - startX) ** 2 + (flip[1] - startY) ** 2)
elif direction == 'R' and not is_same(ball, startX, startY, 3):
flip = (ball[0] + (direction_dict[direction][0] - ball[0]) * 2, ball[1])
feasible.append((flip[0] - startX) ** 2 + (flip[1] - startY) ** 2)
answer.append(min(feasible))
return answer
웬만한 프로그래머스 레벨2 문제보다 어려운 것 같다.