Стиснення булевих формул


17

Синтаксис

~НЕ
/\і
\/чи
tсправжні
fпомилкові
P, Q, FISHі т.д .: змінні

(Оператори задаються в порядку черговості)

Вступ

Деякі булеві формули можна змінити на різні форми, щоб зробити їх коротшими. Наприклад, формула

~(~P /\ ~Q)

може бути змінено на більш коротку форму

P\/Q

при цьому формула

P \/ ~P

може бути змінено на більш коротку форму

t

Виклик

У цих проблемах, ви повинні написати програму , яка при будь-якому булева формули з використанням тільки /\, \/, ~, t, f, дужок, логічні змінних (у верхньому регістрі), і прогалин, виводить коротку форму (оскільки може бути більше одного найкоротшою формою ) в символах цього виразу, який є рівнозначним для всіх призначень змінних. Найкоротший код (будь-якою мовою) виграє. Введення / виведення можна зробити будь-яким розумним чином.

Крім того, оскільки відповіді важко перевірити, було б корисно (але не потрібно) включити коротке пояснення того, як працює код.


У розділі "Виклик" ви не згадуєте жодного пробілу, але ваші приклади мають їх. Чи варто поводитися з ними?
Віктор Стафуса

4
Я думаю, що Флорент полягає в тому, що важко вирішити проблему взагалі, не кажучи вже про гольф. Крім усього іншого, аналізатору необхідно мати можливість визначити, чи мають дві довільні формули однакові умови істинності. Зменшити p ^ ~ p досить просто, якщо p є атомним, але як щодо ((A ^ B) v (A ^ C)) ^ ~ (A ^ (BvC))? Я думаю, що це крута проблема, і мені цікаво побачити деякі відповіді. Але якщо ви хочете короткого вирішення, проблема може зробити А. сприятливішим для гри в гольф, використовуючи позначення префіксів, і B. надаючи список необхідних скорочень.
dfernig

1
У мене є дійсне (гольф) рішення з більш ніж 5000 символів. Це смішно ... Він складається з токенізатора, AST-аналізатора, AST-переписувача та генератора виразів.
Флорент

1
Mathematica може це зробити за один виклик функції ( BooleanMinimize)
Флорент

1
Для запису я маю рішення з 498 символів, чий sha256сум b9c98d088b78c30bb2108008a064a7b95722a4694d90ddad94a025c2eb4ed30a. Я опублікую фактичний код пізніше, оскільки не хочу задушити творчість.
Лілі Чунг

Відповіді:


2

О так, я забув коли-небудь насправді розмістити свою відповідь. Він використовує по суті той самий підхід, який використовує відповідь KSab , але друкує лише найкоротший дійсний вираз.

Python3, 493

e=lambda x:eval(x.replace('\\/','+').replace('/\\','%'),None,w)
class V(int):
 def __add__(s,o):return V(s|o)
 def __mod__(s,o):return V(s*o)
 def __invert__(s):return V(-s+1)
import re;from itertools import product as P;t=V(1);f=V(0);i=input();v=re.findall('[A-Z]+',i)
for k in range(1,len(i)):
 for m in P(''.join(v)+'~/\\tf',repeat=k):
  m=''.join(m)
  try:
   for d in P((V(0),V(1)),repeat=len(v)):
    w=dict(zip(v,d))
    if e(m)!=e(i):raise
  except:continue
  print(m);exit()
print(i)

Зверніть увагу , що хеш - я обчислюється раніше включав символ нового рядка і був перш , ніж я golfed def e(x): returnдоe=lambda x:


1

Пітон 616

Не особливо ефективно, але працює в розумний час для входів, результати яких становлять приблизно 5 або 6 символів. Щоб перевірити рядок, щоб побачити, чи відповідає він, він перебирає всі можливі поєднання значень істини / помилок для всіх змінних і гарантує, що кожна з них погоджується. Використовуючи це, він перевіряє кожен можливий рядок, що складається з відповідних символів (навіть не обов'язково синтаксично правильного).

Він фактично надрукує кожен еквівалентний вираз (будь-якого розміру) і фактично ніколи не припиняється.

Код:

c=['t','f'];o=['1 ','0 ']
def e(s,v):
 for k in v:s=s.replace(k,v[k])
 return eval(s)
def z(t,p='~/\\() '):
 w=[]
 if p=='':return[t]*(t not in['']+c)
 for s in t.split(p[0]):w.extend(z(s,p[1:]))
 w.sort(key=lambda v:-len(v));return w
def m(v):
 l=list('~\\/()')+v
 for s in l:yield s
 for r in m(v):
    for s in l:yield s+r
def n(x):
 if x<1:yield []
 else:
    for l in n(x-1):
     for b in o:yield[b]+l
t=raw_input();v=z(t)+c;l=len(v)
for s in m(v):
 g=1
 for y in n(l):
    y[-2:]=o;d=dict(zip(v+['/\\','\\/','~'],y+['and ','or ','not ']))
    try:
     if e(s,d)!=e(t,d):g=0
    except:g=0
 if g:print s

Введення / вихід:

> ~(~P /\ ~Q)
Q\/P
P\/Q
...

> P /\ ~P
f
~t
...

> (P \/ Q) /\ P
P
(P)
...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.