2

## 【小馬的LeetCode練功坊】858. Mirror Reflection (Medium)

x位移=p，y位移=q，

(右下角: 0、右上角: 1、左上角: 2)

1. 1 <= p <= 1000
2. 0 <= q <= p

# 解法一: 直接模擬光線的動向

``````def close(x,y):
return abs(x-y)<=10**(-5)

def closePos(pos1, pos2):
return abs(pos1[0]-pos2[0])+abs(pos1[1]-pos2[1])<=10**(-5)

class Solution:
def mirrorReflection(self, p: int, q: int) -> int:
direction, pos = [p,q], [0,0]
exits = [[p, 0], [p, p], [0,p]]
# while迴圈，若現在位置還沒靠近出口，就繼續模擬光線走向
while all(not closePos(pos, ex) for ex in exits):
dir_x = p-pos[0] if direction[0]>0 else pos[0]
dir_y = p-pos[1] if direction[1]>0 else pos[1]
rate = min(dir_x/p, dir_y/q) # 看x,y哪個方向先撞牆
pos[0] += direction[0] * rate
pos[1] += direction[1] * rate
# 撞牆就反向
if close(pos[0],0) or close(pos[0],p):
direction[0] *= -1
if close(pos[1],0) or close(pos[1],p):
direction[1] *= -1

# 判斷離哪個出口近
for i in range(3):
if closePos(pos, exits[i]):
return i
``````

# 解法二: 優化模擬- 直接往上走到鏡中世界

``````class Solution:
def mirrorReflection(self, p: int, q: int) -> int:
direction, pos = "left", q #下一步往左走、位置=q
while pos%p!=0:
pos += q
direction = "right" if direction=="left" else "left"
if (pos//p)%2==1: #正常世界
return 2 if direction=="right" else 1
return 0 #鏡中世界
``````

# 解法三: 省去模擬，直接判斷

``````from math import gcd
class Solution:
def mirrorReflection(self, p: int, q: int) -> int:
g = gcd(p, q)
p, q = p//g, q//g
if q%2==1: #正常世界
return 2 if p%2==0 else 1
return 0 #鏡中世界
``````