【问题标题】:Making truthtables in python在python中制作真值表
【发布时间】:2014-02-19 00:51:55
【问题描述】:

我在做一些与用 Python 制作真值表相关的作业时遇到了一些麻烦。我试过去办公时间,但他们什么都不知道,所以我得问问你们。

问题来了:

--

在这个问题中,您将实现打印带有变量的公式的真值表的函数。您可以使用以下帮助函数,它会打印一个制表符分隔的值列表。

def prints(values):
    print("\t".join([str(value) for value in values]))

上面的函数可以如下使用

prints([True, False, True])
True   False  True

您还可以使用以下帮助函数,它返回函数的参数名称列表:

def variables(f):
    return list(f.__code__.co_varnames)

上面的函数可以如下使用:

def h(x,y,z): return (y or x) and (not(z) <= x)

variables(h)
['x', 'y', 'z']

A:实现一个函数truthtableXY(f),它接受一个函数f作为输入(即一个Python函数对应一个公式,比如你在上面的问题2中定义的公式)。你可以假设 f 有两个布尔参数 x 和 y。该函数应打印 f 的真值表。

def f(x,y): return x and y

truthtableXY(f)
y      x      formula
True   True   True
True   False  False
False  True   False
False  False  False

B:实现一个递归函数truthtable(f),它的第一个参数是单个函数f(即对应于公式的Python函数)。函数 f 可以采用任何非零数量的参数。该函数应打印 f 的真值表。

def h(x,y,z): return (y or x) and (not(z) <= x)

truthtable(h)
x       y       z       formula
True    True    True    False
True    True    False   False
True    False   True    False
True    False   False   False
False   True    True    True
False   True    False   False
False   False   True    False
False   False   False   False

您的truthtable() 函数应采用递归回溯方法,并且可以按如下方式组织:

  • 函数应该有第二个参数 values,默认值为 [],这将是函数建立并最终传递给 f 的值列表;
  • 如果列表值为空,该函数应打印包含所有变量名称的行(每个变量一个列标题);
  • 如果列表值与 f 的变量列表长度相同,则函数应打印一行包含 values 中所有值的值,以及将 f 应用于该值列表的结果(使用*-运算符将 f 应用于参数列表);
  • 如果列表值比 f 的变量列表短,该函数应递归调用 truthtable(),并适当更改 truthtable() 的参数。

C:实现一个函数 rows(f),它的第一个参数是单个函数 f(即对应于公式的 Python 函数)。该函数应返回 f 真值表中的行数。

def h(x,y,z): return (y or x) and (not(z) <= x)

rows(h)
8

--

我成功做了A,得到了这个答案:

def truthtableXY(f):
    prints(['y', 'x', 'formula'])
    for x in [True, False]:
        for y in [True, False]:
            prints([x, y, f(x,y)])

有效。但我根本不知道该怎么做。

有谁知道/能找出答案吗?

这是带有作业顺便说一句的原始网站:http://cs-people.bu.edu/lapets/131/m.php?#2.4(问题 3)

提前谢谢各位! :)

【问题讨论】:

  • 你有什么吗? B的步骤很清楚,你到底卡在哪里了?
  • 我什么都没有,不知道从哪里开始或任何事情。以前没有人向我展示过如何做到这一点,所以我完全是空的......

标签: python python-3.x boolean truthtable


【解决方案1】:

嗯,C 部分是微不足道的,那就是2 ** len(variables(h))。对于 B 部分,我建议对变量的所有可能分配使用枚举器。对于赋值,我的意思是一个与变量数组长度相同的布尔数组,因此每个变量都有一个布尔值。

那么你可以在 Python 中使用以下技巧:

>>> def f(x, y, z): return (y or x) and (not(z) <= x)
>>> assignment = [True, False, True]
>>> f(*assignment)
False

这是使用列表中的参数调用函数的技巧。

您现在可以看到,您只需枚举赋值,并检查每个赋值的函数值。

要枚举分配,您还可以使用布尔值只是整数计数器的位这一事实。如果您真的希望它回溯,请使用:

def enumerate_bools(length):
    if length == 0:
        yield []
        return
    for rest in enumerate_bools(length - 1):
        yield [False] + rest
        yield [True]  + rest

【讨论】:

  • 这不使用递归回溯方法。
  • @jonrsharpe:糟糕,忘了那部分。现在可以了。
  • 感谢 c 的回答,就像一个魅力!至于 b 的问题,你介意按照我对 a 部分的回答来解决问题吗?或者至少使用任务中给定/需要的一些功能和名称。我不太明白如何调整您的答案以适应问题...:/提前致谢! :)
  • 不能那样做,那是你的功课。如果您将我的部分与给出的其他答案结合起来,您肯定会到达那里。
【解决方案2】:

首先,我们不使用variables 函数,而是使用inspect 模块定义自己的函数。这样,我们就不必访问内部特定于实现的属性:

import inspect
def variables (f):
    return inspect.getargspec(f).args

对于真值表,我们需要一些组合,所以我们使用itertools 模块:

from itertools import product, repeat
def truthtable (f):
    vars = variables(f)

    # print the header
    prints(vars + ['formula'])

    # get all combinations
    for args in product(*repeat((True, False), len(vars))):
        result = f(*args)
        prints(args + (result,))

使用,我们得到这些结果:

>>> truthtable(f)
x   y   formula
True    True    True
True    False   False
False   True    False
False   False   False
>>> truthtable(h)
x   y   z   formula
True    True    True    False
True    True    False   False
True    False   True    False
True    False   False   False
False   True    True    True
False   True    False   False
False   False   True    False
False   False   False   False

我将把递归函数的实现留给你。毕竟这是你的功课,说明实际上很好地解释了你需要做什么。

至于最后一个任务,这是简单的组合。对于每个变量,我们有两个可能的值。对于我们添加到一组组合中的每个变量,我们必须将所有这些组合一次与True 组合一次,一次与False 组合,这样我们得到两倍。对于只有一个变量的情况,我们只有两种可能性。所以对于n 变量,我们有2 ** n 可能的组合。


好的,让我们逐一阅读说明以使此递归解决方案起作用:

函数应该有第二个参数values,默认值为[],它将是函数建立并最终传递给f的值列表

好的,所以我们的函数将如下所示:

def truthtable (f, values=[]):
    # …

但取而代之的是,我们实际上将设置默认值None 并明确地将其设置为函数内部的一个空列表。你可能会为此打你的导师,因为这是a very common error。

def truthtable (f, values=None):
    if values is None:
        values = []
    # …

如果列表值为空,该函数应打印包含所有变量名称的行(每个变量一个列标题)

好的,这只是调用prints(variables(f)),所以这部分看起来像这样:

if values == []:
    prints(variables(f))

如果列表值与 f 的变量列表长度相同,则该函数应打印一行包含 values 中所有值的值,以及将 f 应用于该值列表的结果(使用*-运算符将 f 应用于参数列表)

同样,这也是直截了当的:

if len(values) == len(variables(f)):
    result = f(*values)
    prints(values + [result])

如果列表值比 f 的变量列表短,该函数应该递归调用truthtable(),并适当更改truthtable() 的参数。

所以这里是递归发生的地方,所以让我们考虑一下。我们从一个空的值列表开始,我们想要达到一个值与变量一样多的点。所以很明显我们想在递归调用函数时将值添加到values 列表中。现在我们要添加哪些值?我们只知道两个值:True 和 False。所以调用看起来像这样:

truthtable(f, values + [True])
truthtable(f, values + [False])

现在我们将所有这些放在一起:

def truthtable (f, values=None):
    if values is None:
        values = []

    if values == []:
        prints(variables(f))

    if len(values) == len(variables(f)):
        result = f(*values)
        prints(values + [result])
    else:
        truthtable(f, values + [True])
        truthtable(f, values + [False])

就是这样。现在,我从一开始就说过,values 的可变默认值对于这个函数并不完全正确,因为我们从不直接修改列表,而只是通过将其与其他列表连接来创建一个新列表;所以我们可以再次恢复。但无论如何我都会保留它,因为您应该始终牢记这一点,否则您迟早会遇到问题。

【讨论】:

  • 感谢您的快速回复,但我不同意说明是明确的。我对此完全陌生,我根本不明白他们想让我做什么。无论如何,您介意使用该变量函数计算出响应吗?我只是想看看它是如何工作的,以及他们具体是怎么想的。在此先感谢:)
  • 我已经更新了答案,逐一浏览规范以创建递归解决方案。
【解决方案3】:

对于 B,你想要:

def truthtable(f, values=None):
    if values is None:
        prints(variables(f) + ["formula"])
        values = []
    # print values 
    if len(values) == len(variables(f)):
        prints(values + [f(*values)])
    else:
        for b in [True, False]:
            truthtable(f, values + [b])

这如何符合您的规范:

  • 函数应该有第二个参数values,默认为 [] 的值,这将是函数建立的值列表 并最终传递给f; - 不完全是,“可变默认参数”在 Python 中是一个糟糕的举动,但我有 values 并在第一次调用 truthtable 时将其设为空列表

  • 如果列表values为空,函数 应该打印包含所有变量名称的行(一列 每个变量的标题); - 在初始化 value

  • 的同时完成
  • 如果列表 values 的长度与 f 的变量列表,函数应该打印一行值 包含values 中的所有值,以及结果 将f 应用于该值列表(使用*-运算符将f 应用于 参数列表); - 第二个if 块

  • 如果列表 values 比列表短 f 的变量,函数应该递归调用 truthtable(),对 truthtable()。 - 最后的for 循环。

关于最后一部分的更多解释;您需要建立True 和False 的组合以作为参数传递给f,因此您首先使用True 递归调用(即从自身内部调用函数)truthtable,然后使用False ,每次都添加到列表中,直到您拥有正确数量的参数。取消注释 print values 以在解释器中观察这种情况。

【讨论】:

  • 非常感谢,正是我想要的! :D
  • 我添加了一些 cmets 来展示你应该如何从规范中将它们组合在一起;递归回溯是唯一没有完全解释的部分。
猜你喜欢
  • 2021-05-07
  • 2021-09-05
  • 1970-01-01
  • 2015-06-03
  • 2016-09-28
  • 2016-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多