Có nhiều hình thức, vì vậy trong khi bạn có thể thấy các nguồn khác hữu ích, tôi hy vọng sẽ chỉ rõ điều này đủ rõ ràng rằng chúng không cần thiết.
Một RM bao gồm một máy trạng thái hữu hạn và một số hữu hạn các thanh ghi có tên, mỗi thanh chứa một số nguyên không âm. Để dễ dàng nhập văn bản, nhiệm vụ này yêu cầu các trạng thái cũng được đặt tên.
Có ba loại trạng thái: tăng và giảm, cả hai đều tham chiếu một thanh ghi cụ thể; và chấm dứt. Một trạng thái tăng làm tăng thanh ghi của nó và chuyển điều khiển cho một người kế vị của nó. Một trạng thái giảm có hai người kế vị: nếu thanh ghi của nó khác không thì nó sẽ giảm giá trị và chuyển quyền điều khiển cho người kế vị đầu tiên; mặt khác (tức là thanh ghi bằng 0) nó chỉ đơn giản chuyển quyền điều khiển cho người kế vị thứ hai.
Đối với "tính độc đáo" là ngôn ngữ lập trình, các trạng thái chấm dứt lấy một chuỗi mã hóa cứng để in (để bạn có thể chỉ ra sự chấm dứt đặc biệt).
Đầu vào là từ stdin. Định dạng đầu vào bao gồm một dòng trên mỗi trạng thái, theo sau là nội dung thanh ghi ban đầu. Dòng đầu tiên là trạng thái ban đầu. BNF cho các dòng trạng thái là:
line ::= inc_line
| dec_line
inc_line ::= label ' : ' reg_name ' + ' state_name
dec_line ::= label ' : ' reg_name ' - ' state_name ' ' state_name
state_name ::= label
| '"' message '"'
label ::= identifier
reg_name ::= identifier
Có một số linh hoạt trong định nghĩa của định danh và thông điệp. Chương trình của bạn phải chấp nhận một chuỗi ký tự chữ và số không trống làm định danh, nhưng nó có thể chấp nhận các chuỗi chung hơn nếu bạn thích (ví dụ: nếu ngôn ngữ của bạn hỗ trợ mã định danh có dấu gạch dưới và bạn dễ dàng làm việc hơn). Tương tự, đối với tin nhắn, bạn phải chấp nhận một chuỗi chữ và số không trống, nhưng bạn có thể chấp nhận các chuỗi phức tạp hơn cho phép thoát các dòng mới và ký tự trích dẫn kép nếu bạn muốn.
Dòng cuối cùng của đầu vào, cung cấp các giá trị thanh ghi ban đầu, là một danh sách định danh được phân tách bằng dấu cách = int gán, phải không trống. Không bắt buộc phải khởi tạo tất cả các thanh ghi có tên trong chương trình: bất kỳ thanh ghi nào không được khởi tạo đều được coi là 0.
Chương trình của bạn nên đọc đầu vào và mô phỏng RM. Khi đạt đến trạng thái kết thúc, nó sẽ phát ra thông báo, dòng mới và sau đó là các giá trị của tất cả các thanh ghi (theo bất kỳ định dạng thuận tiện, dễ đọc của con người, và bất kỳ thứ tự nào).
Lưu ý: chính thức các thanh ghi nên giữ các số nguyên không giới hạn. Tuy nhiên, bạn có thể nếu bạn muốn cho rằng không có giá trị nào của người đăng ký sẽ vượt quá 2 ^ 30.
Một số ví dụ đơn giản
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Kết quả dự kiến:
Ok
a=0 b=7
b + = a, t = 0
init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4
Kết quả dự kiến:
Ok
a=3 b=7 t=0
Các trường hợp thử nghiệm cho các máy khó phân tích hơn
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Kết quả dự kiến:
t is 1
t=1
và
s0 : t - "t is nonzero" "t is zero"
t=1
Kết quả dự kiến:
t is nonzero
t=0
Một ví dụ phức tạp hơn
Lấy từ thử thách mã vấn đề Josephus của DailyWTF. Đầu vào là n (số lượng binh sĩ) và k (tạm ứng) và đầu ra trong r là vị trí (không có chỉ số) của người sống sót.
init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3
Kết quả dự kiến:
Ok
i=40 k=3 n=0 r=27 t=0
Chương trình đó như một bức tranh, dành cho những người suy nghĩ trực quan và sẽ thấy hữu ích khi nắm bắt cú pháp:
Nếu bạn thích môn golf này, hãy xem phần tiếp theo .