Xuất ra một poof chính thức đầy đủ của các tuyên bố như 1+2=3
, 2+2=2*(1+1)
v.v.
Giới thiệu
Nếu bạn biết số học Peano, bạn có thể bỏ qua phần này.
Đây là cách chúng tôi xác định số tự nhiên:
(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.
Do đó, ví dụ S(S(S(0)))
là một số.
Bạn có thể sử dụng bất kỳ đại diện tương đương trong mã của bạn. Ví dụ: tất cả những thứ này đều hợp lệ:
0 "" 0 () !
1 "#" S(0) (()) !'
2 "##" S(S(0)) ((())) !''
3 "###" S(S(S(0))) (((()))) !'''
...
etc
Chúng ta có thể mở rộng các quy tắc để xác định bổ sung như sau.
(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y
Với điều này, chúng ta có thể chứng minh 2 + 2 = 4 như sau
S(S(0)) + S(S(0)) = 2 + 2
[Rule 2 with X=S(S(0)), Y=S(0)]
S(S(S(0))) + S(0) = 3 + 1
[Rule 2 with X=S(S(S(0))), Y=0]
S(S(S(S(0)))) + 0 = 4 + 0
[Rule 1 with X=S(S(S(S(0))))
S(S(S(S(0)))) = 4
Chúng ta có thể mở rộng các quy tắc này để xác định phép nhân như sau
(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X
Mặc dù để cho phép điều này, chúng ta cần xác định vai trò cấu trúc của dấu ngoặc đơn.
(Axiom 3) If X is a number, (X) is the same number.
Toán tử cộng và nhân là nhị phân nghiêm ngặt và dấu ngoặc đơn phải luôn rõ ràng. A+B+C
không được xác định rõ, nhưng (A+B)+C
và A+(B+C)
được.
Thí dụ
Bây giờ chúng ta có đủ để chứng minh một định lý về phép nhân: 2 + 2 = 2 * 2
2 + 2
(2) + 2
(0 + 2) + 2
((0*2) + 2) + 2
(1*2) + 2
2*2
Yêu cầu
Một bằng chứngA=B
là một biểu thức danh sách sao cho:
- đầu tiên là
A
, - cuối cùng là
B
, và - mỗi biểu thức trong danh sách ngoài biểu thức đầu tiên có thể thu được từ trước bằng cách chuyển đổi nó theo một trong các quy tắc.
Chương trình của bạn sẽ lấy hai biểu thức hợp lệ làm đầu vào , mỗi biểu thức chứa số, phép cộng, phép nhân và dấu ngoặc đơn như được định nghĩa ở trên.
Chương trình của bạn sẽ đưa ra một bằng chứng, một danh sách như được định nghĩa ở trên, rằng hai biểu thức bằng nhau, nếu bằng chứng đó tồn tại.
Nếu hai biểu thức không bằng nhau, chương trình của bạn sẽ không có gì.
Việc chứng minh hoặc từ chối luôn luôn có thể trong một số bước hữu hạn, bởi vì mỗi biểu thức có thể được giảm xuống một số duy nhất và những số này có thể được kiểm tra một cách tầm thường cho sự bằng nhau.
Nếu các biểu thức đầu vào không hợp lệ (ví dụ: dấu ngoặc đơn không cân bằng, chứa toán tử không phải là số hoặc toán tử không nhị phân) thì chương trình của bạn sẽ thoát khỏi lỗi, ném ngoại lệ, in lỗi hoặc tạo ra một số hành vi có thể quan sát được khác với trường hợp trong đó các đầu vào là hợp lệ nhưng không bằng nhau .
Tóm lại, đầu ra bình thường cho các đầu vào được chấp nhận là một danh sách các số bằng nhau, bao gồm các đầu vào, được tạo ra bởi các quy tắc sau.
(Axiom 1) 0 is a number
(Axiom 2) If `x` is a number, the `S(x)`, the successor of `x`, is a number.
(Axiom 3) If X is a number, (X) is the same number
(Rule 1) X+0 = X
(Rule 2) X+S(Y)=S(X)+Y
(Rule 3) X*0 = 0
(Rule 4) X*S(Y) = (X*Y) + X
(Rule 5) X = (X) (Axiom 3 expressed as a transformation rule.)
Bất kỳ đại diện thích hợp của những con số trong đầu vào và đầu ra được cho phép, ví dụ 0=""=()
, 3="###"=(((())))
vv Khoảng trắng là không thích hợp.
Tất nhiên, các quy tắc có thể được áp dụng theo một trong hai hướng. Chương trình của bạn không phải xuất ra quy tắc nào được sử dụng, chỉ là biểu thức được tạo bởi hành động của nó trên biểu thức trước đó.
Mã ngắn nhất sẽ thắng.