Compressione di formule booleane


17

Sintassi

~Non
/\e
\/o
tveri e propri
ffalsi
P, Q, FISH, ecc: variabili

(Gli operatori sono indicati in ordine di precedenza)

introduzione

Alcune formule booleane possono essere modificate in forme diverse per renderle più brevi. Ad esempio, la formula

~(~P /\ ~Q)

può essere modificato nella forma più breve

P\/Q

mentre la formula

P \/ ~P

può essere modificato nella forma più breve

t

Sfida

In questa sfida, si sono tenuti a scrivere un programma che, data qualsiasi formula booleana utilizzando solo /\, \/, ~, t, f, parentesi, le variabili booleane (in maiuscolo) e gli spazi bianchi, emette una forma più breve (dal momento che ci possono essere più di una forma più breve ) in caratteri di quell'espressione che è equivalente per tutte le assegnazioni delle variabili. Vince il codice più breve (in qualsiasi lingua). L'I / O può essere eseguito in modo ragionevole.

Inoltre, poiché le risposte sono difficili da verificare, sarebbe utile (ma non necessario) includere una breve spiegazione del funzionamento del codice.


Nella sezione "Sfida" non menzioni spazi bianchi, ma i tuoi esempi li hanno. Devo gestirli?
Victor Stafusa,

4
Penso che il punto di Florent sia che è un problema difficile da risolvere in generale, per non parlare del golf. Tra le altre cose, il parser dovrà essere in grado di determinare se due formule arbitrarie hanno le stesse condizioni di verità. Ridurre p ^ ~ p è abbastanza facile se p è atomico, ma che ne dici di ((A ^ B) v (A ^ C)) ^ ~ (A ^ (BvC))? Penso che sia un bel problema e sono curioso di vedere alcune risposte. Ma se vuoi soluzioni brevi, il problema potrebbe essere reso più favorevole al golf da A. usando la notazione con prefisso e B. fornendo un elenco di riduzioni richieste.
dfernig,

1
Ho una soluzione valida (giocata a golf) con più di 5000 caratteri. Questo è ridicolo ... È composto da un tokenizer, un parser AST, un riscrittore AST e un generatore di espressioni.
Florent,

1
Mathematica può farlo in una chiamata di funzione ( BooleanMinimize)
Florent

1
Per la cronaca, ora ho una soluzione di 498 caratteri, il cui sha256sum è b9c98d088b78c30bb2108008a064a7b95722a4694d90ddad94a025c2eb4ed30a. Pubblicherò il codice attuale in un secondo momento, poiché non voglio soffocare la creatività.
Lily Chung,

Risposte:


2

Oh giusto, ho dimenticato di pubblicare davvero la mia risposta. Utilizza essenzialmente lo stesso identico approccio usato dalla risposta di KSab , ma stampa solo l'espressione valida più breve.

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)

Si noti che l'hash che ho calcolato in precedenza includeva la newline finale e prima di giocare def e(x): returna golfe=lambda x:


1

Python 616

Non particolarmente efficiente, ma funziona in tempi ragionevoli per input i cui risultati sono circa 5 o 6 caratteri. Per controllare una stringa per vedere se corrisponde, passa in rassegna ogni possibile combinazione di valori verità / falsi per tutte le variabili e si assicura che ognuno sia d'accordo. Usando questo controlla ogni possibile stringa composta dai caratteri rilevanti (nemmeno necessariamente sintatticamente corretta).

In realtà stamperà ogni espressione equivalente (di ogni dimensione) e non terminerà mai.

Codice:

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

Input / Ouput:

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

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

> (P \/ Q) /\ P
P
(P)
...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.