Compression des formules booléennes


17

Syntaxe

~pas
/\et
\/ou
tvrai
ffaux
P, Q, FISH, etc: les variables

(Les opérateurs sont indiqués par ordre de priorité)

introduction

Certaines formules booléennes peuvent être modifiées en différentes formes pour les raccourcir. Par exemple, la formule

~(~P /\ ~Q)

peut être changé en forme plus courte

P\/Q

tandis que la formule

P \/ ~P

peut être changé en forme plus courte

t

Défi

Dans ce défi, vous devez écrire un programme qui, étant donné une formule booléenne en utilisant seulement /\, \/, ~, t, f, entre parenthèses, les variables booléennes (en majuscules), et les espaces, émet une forme plus courte (car il peut y avoir plus d'une forme plus courte ) en caractères de cette expression qui est équivalente pour toutes les affectations des variables. Le code le plus court (dans n'importe quelle langue) gagne. Les E / S peuvent être effectuées de toute manière raisonnable.

De plus, comme les réponses sont difficiles à vérifier, il serait utile (mais pas obligatoire) d'inclure une brève explication du fonctionnement du code.


Dans votre section "Challenge", vous ne mentionnez aucun espace, mais vos exemples en contiennent. Dois-je les manipuler?
Victor Stafusa

4
Je pense que le point de Florent est que c'est un problème difficile à résoudre en général, sans parler du golf. Entre autres choses, l'analyseur devra être en mesure de déterminer si deux formules arbitraires ont les mêmes conditions de vérité. Réduire p ^ ~ p est assez facile si p est atomique, mais qu'en est-il de ((A ^ B) v (A ^ C)) ^ ~ (A ^ (BvC))? Je pense que c'est un problème cool et je suis curieux de voir quelques réponses. Mais si vous voulez des solutions courtes, le problème pourrait être rendu plus propice au golf par A. en utilisant la notation de préfixe et B. en fournissant une liste des réductions requises.
dfernig

1
J'ai une solution valide (golfée) en plus de 5000 caractères. C'est ridicule ... Il est composé d'un tokenizer, d'un analyseur AST, d'un réécriteur AST et d'un générateur d'expression.
Florent

1
Mathematica peut le faire en un seul appel de fonction ( BooleanMinimize)
Florent

1
Pour mémoire, j'ai maintenant une solution de 498 caractères, dont la somme sha256 est b9c98d088b78c30bb2108008a064a7b95722a4694d90ddad94a025c2eb4ed30a. Je posterai le code réel à une date ultérieure, car je ne veux pas étouffer la créativité.
Lily Chung

Réponses:


2

Oh oui, j'ai oublié de poster ma réponse. Il utilise essentiellement la même approche exacte que celle utilisée par la réponse de KSab , mais n'imprime que l'expression valide la plus courte.

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)

Notez que le hachage que j'ai calculé plus tôt incluait la nouvelle ligne de fin et était avant de jouer def e(x): returnau golf poure=lambda x:


1

Python 616

Pas particulièrement efficace, mais fonctionne dans un délai raisonnable pour les entrées dont les résultats sont d'environ 5 ou 6 caractères. Pour vérifier une chaîne pour voir si elle correspond, elle parcourt toutes les combinaisons possibles de valeurs vrai / faux pour toutes les variables et s'assure que chacune est d'accord. En utilisant cela, il vérifie chaque chaîne possible composée des caractères pertinents (pas même nécessairement une syntaxiquement correcte).

Il affichera en fait toutes les expressions équivalentes (de toutes les tailles) et ne se terminera jamais.

Code:

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

Entrée / sortie:

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

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

> (P \/ Q) /\ P
P
(P)
...
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.