修复逻辑系统


16

您将获得一组逻辑语句。您的挑战是,以最佳方式(即删除最少数量的语句)删除任何与其他矛盾的语句。

挑战

您将编写一个程序或函数,该程序或函数将语句列表作为输入,删除最少数量的语句,以便找到解决方案,然后输出其余的语句。

逻辑

语句由变量 A-Z和它们之间的运算符组成。

有5个运算符-(not),v(or),^(and),->(if)和<->(iff)。

真相表:

A | B | -A | AvB | A^B | A->B | A<->B
0 | 0 |  1 |  0  |  0  |   1  |   1
0 | 1 |  1 |  1  |  0  |   1  |   0
1 | 0 |  0 |  1  |  0  |   0  |   0
1 | 1 |  0 |  1  |  1  |   1  |   1

这些运算符可以与括号组合在一起()

A | B | -(AvB) | Av(-A) | A^(-A) | (AvB)->(-B)
0 | 0 |    1   |    1   |    0   |      1
0 | 1 |    0   |    1   |    0   |      0
1 | 0 |    0   |    1   |    0   |      1
1 | 1 |    0   |    1   |    0   |      0

逻辑系统由1个或多个语句组成

溶液逻辑系统是所有的状态语句是同时真。

逻辑系统示例:

AvB
-(A<->B)
(AvB)->(-B)

唯一的解决方案A = 1, B = 0

A^B
-(B<->A)

这个没有解决办法 ; 没有任何组合,A并且B两个陈述均正确。

输入值

您将收到一组语句作为输入。这可以通过STDIN或函数参数获取,格式为数组(以方便的格式)或换行符分隔或空格分隔的字符串。

这些语句将采用以下形式(几乎为ABNF):

statement        = variable / operation
operation        = not-operation / binary-operation
not-operation    = "-" operand
binary-operation = operand binary-operator operand
operand          = variable / "(" operation ")"
variable         = "A"-"Z"
binary-operator  = "v" / "^" / "->" / "<->"

语句示例:

A
Av(-B)
(A<->(Q^C))v((-B)vH)

输出量

您必须以收到的确切格式返回(可能)简化的语句集。同样,列表可以设置为字符串数组或换行符分隔或空格分隔的格式。

规则

  • 您应该始终删除最少数量的语句。如果有多个可能的解决方案,请输出其中之一。
  • 您可以假定输入始终包含至少1条语句,并且在输入中不重复任何语句。
  • 您可能不会假定输出始终包含一条语句。(请参见示例)
  • 使用标准漏洞与您的答案有效不符,必须删除其中之一。
  • 这是,因此最短的答案以字节为单位。

例子

输入:

A^(-A)

输出:

(nothing)

输入:

A^B A<->(-B) A<->B

输出:

A^B A<->B

输入:

["AvB","A^B"]

输出:

["AvB","A^B"]

3
我不知道这是否相关,但是这个问题归结为最大包装数量,这是NP完整的。
Leif Willerts 2015年

根据您的语法,示例中的第三条陈述不正确((AvB)->-B应该是(AvB)->(-B)
骄傲的haskeller 2015年

@proudhaskeller谢谢,改正了这个问题。
PurkkaKoodari

另外,括号在 A<->(Q^C))v((-B)vH捣碎。
2015年

@proudhaskeller再次感谢。
PurkkaKoodari 2015年

Answers:


3

红宝石,299个 298 283 279字节

class Object;def * o;!self|o;end;def s;w=join.gsub(/\W/,"").chars.uniq;n=w.size;(0..2**n).any?{|i|n.times{|j|eval(w[j]+"=#{i[j]>0}")};all?{|e|eval([%w[<-> ==],%w[-> *],%w[- !],%w[^ &],%w[v |]].inject(e){|x,i|x.gsub(*i)})}}?self:combination(size-1).map(&:s).max_by(&:size);end;end
  • 需要一个表达式数组。
  • 如果要运行它,请在ruby内部设置$ VERBOSE = nil,这样就不会收到有关重新定义常量的大量警告。
  • 注意,它实际上也设置了变量“ v”,但没有区别。
  • 使用真值,因为它们已经具有除隐含值之外的所有必需运算符。不幸的是,Ruby没有boolean类,因此我们必须Monkey-patch Object来暗示:)
  • 如果仅设置所有大写变量,则可以使其更短,但是运行将花费大量时间。应该对此有一个警告。

取消高尔夫:

class Object
  def * o 
    !self|o
  end 
end

def sat? exs 
  #exs: an array of expressions
  s=[%w[<-> ==], %w[-> *], "-!", "^&", %w[v ||]]

  w=exs.join.gsub(/\W/,"").chars.uniq #variable names
  n=w.size
  if (0...2**n).any? {|i|
    n.times do |vi|
      eval("#{w[vi]}=#{i[vi]==1}")
    end 
    exs.all?{|ex|eval(s.inject(ex){|x,i|x.gsub(i[0],i[1])})}
  }
    exs
  else
    exs.combination(exs.size-1).map{|sm|sat?(sm)}.max_by(&:size)
  end
end

5

Python 3,431个字节

现在还不太打高尔夫球,但我想我会得到一个答案。在这里尝试,g()是主要功能。

import re,itertools as H
def g(i):
 y=re.sub(r'\W','',''.join(set(i)).upper());l=i.split()
 def e(s):
  def f(a):
   for v,w in a:exec(v+'='+w)
   return eval(re.sub('[^A-Z()]+',lambda x:{'v':' or ','^':'*','<->':'==','->':'<=','-':'not '}[x.group()],s))
  return[c for c in H.product("01",repeat=len(y))if f(zip(y,c))]
 for n in range(len(l),-1,-1):
  for q in H.combinations(l,n):
   if e('('+')^('.join(q)+')'):return' '.join(q)

很酷。我将其降至428:repl.it/BCzp
PurkkaKoodari 2015年

您建模真值的方式存在问题。例如,g(“ A(AvA)<-> A”)应该返回其输入,但是它不起作用,因为如果A = 1,则AvA = 2。
易卜拉欣·滕瑟

啊哈,您是对的,感谢您指出。由于我想不出一种比较短的方法,因此现在将其还原为“和”。也感谢您对高尔夫的改变Pietu!
TheMadHaberdasher 2015年

我相信vor
PurkkaKoodari

...是。谢谢。
TheMadHaberdasher's
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.