Chứng minh 2 + 2 = 2 * 2 (và tương tự)


12

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+Ckhông được xác định rõ, nhưng (A+B)+CA+(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.


Câu trả lời:


5

Perl, 166 + 1 byte

Chạy với -p(1 byte hình phạt).

$r='\((S*)';(@b,@a)=@a;push@a,$_ while+s/\+S/S+/||s/$r\+\)/$1/||s/$r\*\)//||s/$r\*S(S*)/(($1*$2)+$1/||s/$r\)/$1/;$\.=/[^S]./s;$_=$b[-1]eq$a[-1]?join'',@b,reverse@a:""

Dễ đọc hơn:

                           # ẩn: đọc một dòng đầu vào thành $ _
                           # chúng tôi rời khỏi dòng mới trên
$ r = '\ ((S *)'; # chúng tôi sử dụng đoạn regex này rất nhiều, hãy tính nó ra
(@b, @a) = @a; # đặt @b thành @a, @a để trống
đẩy @a, $ _ trong khi # mỗi lần làm tròn vòng lặp, nối $ _ vào @a
+ s / \ + S / S + / | | # quy tắc 2: thay đổi "+ S" thành "S +"
s / $ r \ + \) / $ 1 / || # quy tắc 1: thay đổi "(X + 0)" thành "X"
s / $ r \ * \) // || # quy tắc 3: thay đổi "(X * 0)" thành ""
s / $ r \ * S (S *) / (($ 1 * $ 2) + $ 1 / || # quy tắc 4: thay đổi "(X * Y" thành "((X * Y) + X"
s / $ r \) / $ 1 /; # quy tắc 5: thay đổi "(X) thành" X "
$ \. = / [^ S] ./ s; # nối thêm 1 vào ký tự dòng mới nếu chúng ta
                           # thấy bất kỳ S không theo sau bởi bất cứ điều gì
$ _ = $ b [-1] eq $ a [-1]? # nếu @b và @a kết thúc theo cùng một cách
  tham gia '', @ b, đảo ngược @ a # rồi $ _ trở thành @b theo sau (@a ngược)
  : "" # nếu không trống $ _
                           # ẩn: đầu ra $ _

Định dạng đầu vào biểu thị các số ở dạng đơn nhất là các chuỗi Svà yêu cầu hai đầu vào trên các dòng riêng biệt (mỗi dòng được theo sau bởi một dòng mới và EOF sau khi cả hai được nhìn thấy). Tôi giải thích câu hỏi là yêu cầu dấu ngoặc đơn phải theo nghĩa đen ( )và phép cộng / phép nhân phải theo nghĩa đen + *; Tôi có thể lưu một vài byte thông qua việc thoát ít hơn nếu tôi được phép đưa ra các lựa chọn khác nhau.

Thuật toán thực sự so sánh dòng đầu tiên với một dòng trống, dòng thứ hai với dòng đầu tiên, dòng thứ ba với dòng thứ hai, v.v. Điều này đáp ứng các yêu cầu của câu hỏi. Đây là một ví dụ chạy:

Đầu vào của tôi:

(SS + SS)
(SS * SS)

Đầu ra chương trình:

(SSS + S)
(SSSS +)
SSSS
SSSS
(SSSS +)
((SS +) SS +)
(((SS *) SS +) SS +)
(((SS *) S + S) SS +)
(((SS *) + SS) SS +)
((SS * S) SS +)
((SS * S) S + S)
((SS * S) + SS)

Việc sao chép SSSSở giữa là gây phiền nhiễu nhưng tôi đã quyết định rằng nó không vi phạm đặc điểm kỹ thuật và sẽ để lại ít byte hơn.

Trên đầu vào không hợp lệ, tôi thêm 1vào ký tự dòng mới, do đó bạn sẽ nhận được thông báo đi lạc 1ở cuối đầu ra.


echo -e "((SS+)+(S+S))\nSS*SS" | perl -p /tmp/x.plđầu ra 1.
bong gân

Điều đó đúng, bạn đang thiếu dấu ngoặc trên dòng thứ hai (có thể nói là (SS*SS) ). "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."
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.