2012-02-01 12 views
38

Tôi cần viết bốn số if s bằng Python. Chú ý những gì nó làm, đang thay đổi giữa bốn trạng thái có thể trong một vòng lặp: 1,0 -> 0,1 -> -1,0 -> 0,-1 và quay lại đầu tiên.Có cách nào để viết những ifs đẹp hơn?

if [dx, dy] == [1,0]: 
    dx, dy = 0, 1 
if [dx, dy] == 0, 1: 
    dx, dy = -1, 0 
if [dx, dy] == [-1, 0] 
    dx, dy = 0, -1 
if [dx, dy] == [0, -1]: 
    dx, dy = 1, 0 

Bất kỳ ai cũng có thể gợi ý cho tôi cách viết hay hơn?

+8

Tôi không phải là chuyên gia về python, nhưng nó trông giống như bảng chuyển đổi trạng thái, vì vậy tôi sẽ gắn chúng vào một dict nơi khóa là từ trạng thái và giá trị là trạng thái. –

+9

Ý của bạn là 'elif' trên dòng 3,5,7? Bởi vì khi nó đứng 1.0 sẽ được đưa vào một con ngỗng hoang dã theo đuổi trở lại 1,0 lần nữa! – wim

+0

@wim: Trên thực tế, '1, 0' sẽ trở thành' 0, 1' như mong đợi, vì '[dx, dy] == 0, 1' luôn sai. –

Trả lời

156
dx, dy = -dy, dx 

Khi nghi ngờ, hãy áp dụng toán học. ;)

+2

Ah, đơn giản :-) – stiank81

55

Magnus' gợi ý là không thể phủ nhận câu trả lời đúng cho câu hỏi của bạn như được đặt ra, nhưng nói chung, bạn muốn sử dụng một từ điển cho các vấn đề như thế này:

statemap = {(1, 0): (0, 1), (0, 1): (-1, 0), (-1, 0): (0, -1), (0, -1): (1, 0)} 

dx, dy = statemap[dx, dy] 

Ngay cả trong trường hợp này tôi thể tranh luận bằng cách sử dụng một từ điển là tốt hơn, vì nó rõ ràng rằng có chính xác bốn tiểu bang và rằng họ lặp lại, nhưng thật khó để chống lại vẻ đẹp tuyệt của tất cả các toán học.

Bằng cách này, các mã trong câu hỏi của bạn có một lỗi trong nó, và, giả định rằng các giá trị bạn kiểm tra là những giá trị chỉ có thể, tương đương với:

dx, dy = 1, 0 

Lỗi là bạn cần elif cho điều kiện thứ hai và tiếp theo, nếu không bạn sẽ tiếp tục thử nghiệm dxdy sau khi thay đổi chúng. Nếu chúng là 10, thì tất cả các điều kiện của bạn sẽ là đúng và chúng sẽ kết thúc giống nhau ở cuối! Nếu chúng bắt đầu là 01 thì điều kiện thứ hai và tất cả các điều kiện tiếp theo sẽ là đúng và bạn lại kết thúc với 1, 0. Và cứ như vậy ...

6

Trong khi tôi sẽ đi với Magnus' câu trả lời, đây là thêm một cách tiếp cận để quay trên một tập hợp các giá trị:

def rotate(*states): 
    while 1: 
     for state in states: 
      yield state 

for dx, dy in rotate((1, 0), (0, 1), (-1, 0), (0, -1)): 
    pass 

Lưu ý rằng cần có một break đâu đó trong for dx, dy vòng lặp hoặc nếu không nó sẽ không bao giờ kết thúc.

+4

['itertools.cycle (...)'] (http://docs.python.org/library/itertools.html#itertools.cycle), trong khi không phải là một trình đơn thả xuống chính xác cho 'xoay' của bạn, có thể giải quyết cùng một vấn đề. –

+0

Thật vậy, quên về 'chu kỳ'. Cảm ơn. – yak

18

Các giá trị bạn đang làm việc có vẻ như là một vectơ đơn vị liên tục quay - nói cách khác là phasor. Complex numbers are coordinates, vì vậy:

# at initialization 
phase = 1 
# at the point of modification 
phase *= 1j 
dx, dy = phase.real, phase.imag 

Giả giải thích của tôi về ý nghĩa của dx, giá trị dy là đúng, điều này giúp bạn linh hoạt bổ sung trong trường hợp nó quay ra sau mà bạn muốn xoay bởi một số lượng khác trong mỗi bước.

31

Chỉ cần mở rộng câu trả lời Magnus. Nếu bạn tưởng tượng [dx, dy] dưới dạng vec-tơ, những gì bạn đang thực sự làm là rotation của 90 độ (hoặc PI/2).

Để tính toán này, bạn có thể sử dụng sự chuyển đổi sau:

two dimensional rotation

Mà trong trường hợp của bạn dịch để:

x = x * cos(90) - y * sin(90) 
y = x * sin(90) + y * cos(90) 

Kể từ sin(90) = 1cos(90) = 0 chúng ta đơn giản hóa nó để:

x, y = -y, x 

Và ở đó bạn có nó!

+5

Mặc dù Magnus Hoff có thể có 1 cho sự sang trọng, tôi tin rằng điều này sẽ là 1 cho các nguồn gốc của sự thanh lịch. – oaxacamatt

+0

Nó cũng thể hiện mối quan hệ giữa câu trả lời của Magnus Hoff và của tôi. –