Chuyển đổi một biểu thức logic thành dạng bình thường kết hợp


10

Mục tiêu:

Viết một chương trình hoàn chỉnh hoặc chức năng mà phải mất một công thức trong logic mệnh đề (từ đó được gọi là một biểu thức logic hoặc biểu hiện ) và đầu ra rằng công thức trong dạng chuẩn hội . Có hai hằng số, đại diện cho đúng và sai, một nhà điều hành unary ¬đại diện cho phủ, và các nhà khai thác nhị phân , , , và đại diện cho ý nghĩa, tương đương, kết hợp, và phân ly, tương ứng mà tuân theo tất cả các phép toán logic thông thường ( luật DeMorgan của , loại bỏ phủ định kép , Vân vân.).

Hình thức bình thường kết hợp được định nghĩa như sau:

  1. Bất kỳ biểu hiện nguyên tử (bao gồm ) là ở dạng kết hợp bình thường.
  2. Sự phủ định của bất kỳ biểu thức được xây dựng trước đó là ở dạng kết hợp bình thường.
  3. Sự khác biệt của bất kỳ hai biểu thức được xây dựng trước đó là ở dạng kết hợp bình thường.
  4. Sự kết hợp của bất kỳ hai biểu thức được xây dựng trước đó là ở dạng kết hợp bình thường.
  5. Bất kỳ biểu hiện khác không ở dạng kết hợp bình thường.

Bất kỳ biểu thức logic nào cũng có thể được chuyển đổi (không duy nhất) thành biểu thức tương đương logic ở dạng bình thường kết hợp (xem thuật toán này ). Bạn không cần phải sử dụng thuật toán cụ thể đó.

Đầu vào:

Bạn có thể lấy đầu vào ở bất kỳ định dạng thuận tiện; ví dụ: một biểu thức logic tượng trưng (nếu ngôn ngữ của bạn hỗ trợ nó), một chuỗi, một số cấu trúc dữ liệu khác. Bạn không cần phải sử dụng cùng các ký hiệu cho các toán tử đúng, sai và logic như tôi làm ở đây, nhưng lựa chọn của bạn phải nhất quán và bạn nên giải thích các lựa chọn của mình trong câu trả lời nếu không rõ ràng. Bạn không được chấp nhận bất kỳ đầu vào nào khác hoặc mã hóa bất kỳ thông tin bổ sung nào trong định dạng đầu vào của bạn. Bạn nên có một số cách để thể hiện một số biểu thức nguyên tử tùy ý; ví dụ: số nguyên, ký tự, chuỗi, v.v.

Đầu ra:

Các công thức ở dạng kết hợp bình thường, một lần nữa trong bất kỳ định dạng thuận tiện. Nó không cần phải ở cùng định dạng với đầu vào của bạn, nhưng bạn nên giải thích nếu có bất kỳ sự khác biệt nào.

Các trường hợp thử nghiệm:

P ∧ (P ⇒ R) -> P ∧ R
P ⇔ (¬ P) -> ⊥
(¬ P) ∨ (Q ⇔ (P ∧ R)) -> ((¬ P) ∨ ((¬ Q) ∨ R)) ∧ ((¬ P) ∨ (Q ∨ (¬ R)))

Ghi chú:

  1. Nếu biểu thức đầu vào là một tautology, sẽ là một đầu ra hợp lệ. Tương tự, nếu biểu thức đầu vào là một mâu thuẫn, sẽ là một đầu ra hợp lệ.
  2. Cả hai định dạng đầu vào và đầu ra của bạn phải có thứ tự hoạt động được xác định rõ có khả năng diễn đạt tất cả các biểu thức logic có thể. Bạn có thể cần dấu ngoặc đơn của một số loại.
  3. Bạn có thể sử dụng bất kỳ lựa chọn nào được xác định rõ về ký hiệu infix, tiền tố hoặc hậu tố cho các hoạt động logic. Nếu sự lựa chọn của bạn khác với tiêu chuẩn (phủ định là tiền tố, phần còn lại là infix), vui lòng giải thích điều đó trong câu trả lời của bạn.
  4. Hình thức bình thường kết hợp không phải là duy nhất nói chung (thậm chí không sắp xếp lại). Bạn chỉ cần xuất ra một hình thức hợp lệ.
  5. Tuy nhiên, bạn đại diện cho các biểu thức nguyên tử, chúng phải khác biệt với các hằng số logic, toán tử và các ký hiệu nhóm (nếu bạn có chúng).
  6. Được xây dựng trong đó tính toán hình thức kết hợp bình thường được cho phép.
  7. Sơ hở tiêu chuẩn bị cấm.
  8. Đây là ; câu trả lời ngắn nhất (tính bằng byte) thắng.


1
CNF không phải là duy nhất để sắp xếp lại: các biểu thức tương đương P(P ∨ Q) ∧ (P ∨ (¬Q))đều ở dạng kết hợp thông thường.
Greg Martin

1
Kiểm tra tautology / mâu thuẫn là một nhiệm vụ thứ hai không liên quan đến chuyển đổi CNF, vì vậy tôi sẽ đề nghị bỏ yêu cầu này và đưa vào thử thách của riêng mình.
Laikoni

@Laikoni Rất đúng. Tôi đã cập nhật câu hỏi để nói rằng đó là những đầu ra có thể cho tautology và mâu thuẫn hơn là đầu ra bắt buộc.
ngenisis

Câu trả lời:



8

Bạn sẽ ghét tôi ....

Toán học, 23 byte

#~BooleanConvert~"CNF"&

Các đầu vào sẽ sử dụng TrueFalsethay , nhưng nếu không sẽ trông rất giống với các ký hiệu của câu hỏi: tất cả các nhân vật ¬, , , , và được ghi nhận trong Mathematica (khi đầu vào với UTF-8 ký tự 00AC, F523, 29E6, 2227 và 2228, tương ứng) và dấu ngoặc đơn hoạt động như bạn mong đợi.

Theo mặc định, đầu ra sẽ sử dụng các ký hiệu ưa thích của Mathicala: ví dụ: trường hợp thử nghiệm cuối cùng sẽ xuất ra (! P || ! Q || R) && (! P || Q || ! R)thay vì ((¬ P) ∨ ((¬ Q) ∨ R)) ∧ ((¬ P) ∨ (Q ∨ (¬ R))). Tuy nhiên, thay đổi chức năng thành

TraditionalForm[#~BooleanConvert~"CNF"]&

sẽ làm cho đầu ra trông đẹp và phù hợp với các biểu tượng thông thường này:

hình thức truyền thống


2

JavaScript (ES6), 127 byte

f=(s,t='',p=s.match(/[A-Z]/),r=RegExp(p,'g'))=>p?'('+f(s.replace(r,1),t+'|'+p)+')&('+f(s.replace(r,0),t+'|!'+p)+')':eval(s)?1:0+t

Định dạng I / O như sau (theo thứ tự ưu tiên):

  • (: (
  • ): )
  • : 1
  • : 0
  • ¬: !
  • : <=
  • : ==
  • : &
  • : |

Ví dụ:

P&(P<=R) -> ((1)&(0|P|!R))&((0|!P|R)&(0|!P|!R))
P==(!P) -> (0|P)&(0|!P)
(!P)|(Q==(P&R)) -> (((1)&(0|P|Q|!R))&((0|P|!Q|R)&(1)))&(((1)&(1))&((1)&(1)))

Hàm này được viết lại một cách tầm thường để tạo ra dạng bình thường rời rạc:

f=(s,t='',p=s.match(/[A-Z]/),r=RegExp(p,'g'))=>p?'('f(s.replace(r,1),t+'&'+p)+')|('+f(s.replace(r,0),t+'&!'+p)+')':eval(s)?1+t:0

8 byte có thể được lưu từ phiên bản này nếu tôi cũng được phép đảm nhận quyền ưu tiên ở trên, điều này sẽ loại bỏ tất cả các dấu ngoặc đơn khỏi các ví dụ đầu ra:

P&(P<=R) -> ((1&P&R)|(0))|((0)|(0))
P==(!P) -> (0)|(0)
(!P)|(Q==(P&R)) -> (((1&P&Q&R)|(0))|((0)|(1&P&!Q&!R)))|(((1&!P&Q&R)|(1&!P&Q&!R))|((1&!P&!Q&R)|(1&!P&!Q&!R)))
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.