压缩布尔公式


17

句法

~
/\
\/
t
f
PQFISH,等:变量

(运算符按优先顺序给出)

介绍

可以将某些布尔公式更改为不同的形式以使其更短。例如,公式

~(~P /\ ~Q)

可以更改为较短的形式

P\/Q

而公式

P \/ ~P

可以更改为较短的形式

t

挑战

在这一挑战,则需要编写一个程序,给定仅使用任何布尔式/\\/~tf,括号,布尔变量(大写)和空白,输出一个最短的形式(由于可能存在多于一个的最短形式),该表达式的字符对于所有变量分配都是等效的。最短的代码(使用任何语言)均获胜。I / O可以任何合理的方式完成。

另外,由于很难验证答案,因此包括(但不是必需的)简短说明代码的工作原理将很有帮助。


在“挑战”部分中,您没有提及任何空格,但是示例中有它们。我应该处理吗?
Victor Stafusa 2014年

4
我认为弗洛伦特的观点是,通常来说这是一个很难解决的问题,更不用说打高尔夫球了。其中,解析器将需要能够确定两个任意公式是否具有相同的真值条件。如果p是原子的话,还原p ^〜p很容易,但是((A ^ B)v(A ^ C))^〜(A ^(BvC))呢?我认为这是一个很酷的问题,我很好奇看到一些回应。但是,如果您需要简短的解决方案,则可以通过A.使用前缀表示法和B.提供所需减少量的列表来使问题更有利于打高尔夫球。
dfernig 2014年

1
我有一个超过5000个字符的有效(高尔夫)解决方案。这太荒谬了。它由一个分词器,一个AST解析器,一个AST重写器和一个表达式生成器组成。
Florent 2014年

1
Mathematica可以通过一个函数调用(BooleanMinimize
佛罗伦萨

1
作为记录,我现在有一个498个字符的解决方案,其sha256sum为b9c98d088b78c30bb2108008a064a7b95722a4694d90ddad94a025c2eb4ed30a。我将在以后发布实际代码,因为我不想抑制创造力。
莉莉·钟

Answers:


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): returne=lambda x:


1

Python 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)
...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.