📜  门| GATE-CS-2014-(Set-3) |问题 28(1)

📅  最后修改于: 2023-12-03 14:58:29.603000             🧑  作者: Mango

门 | GATE-CS-2014-(Set-3) | 问题 28

本题目是计算机科学门类的GATE考试中的一道难度较高的题目。

题目描述

给定一个由n个门组成的电路图,其输入和输出位于边缘门处。 电路图的每个门有两个输入和一个输出。在输入上,每个门可以有一个布尔表达式,并有一个描述为Y的默认值。如果门的两个输入变量具有值,则门的输出等于布尔表达式的值。 否则,输出等于Y的值。 假设所有变量(门和默认值)的名称互不相同。

现在给定电路图的描述,以及其边缘门的输入值。 你需要确定连通到输出门的所有门和它们的用户名和值。

你的任务是编写一个python函数,该函数应该满足以下要求:

输入

该函数的输入参数是:

  • n:一个整数,表示门的数量。
  • edges:一个长度为n的元组列表,其中每个元素表示一个门。 元组的前两个值分别表示该门的两个输入名称。 第三个值表示该门的输出名称。 最后一个值是一个长度为m的列表,表示该门的布尔表达式。
  • defaults:一个字典,表示默认值。 字典的键是门名称,值是0或1。
  • inputs:一个字典,表示输入值。 字典的键是门名称,值是0或1。
输出

该函数的输出应该是一个元组列表,其中每个元素表示一个输出门。 元组的第一个值应该是输出门的名称,第二个值应该是其值(0或1),第三个值应该是一个字典,表示该门的所有输入门和它们的值。 字典的键是输入门的名称,值是0或1。

示例

输入

n = 4
edges = [('A', 'B', 'C', ['A or B']), ('C', 'D', 'E', ['not C'])]
defaults = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0}
inputs = {'A': 0, 'B': 1}

输出

[('E', 1, {'C': 0}), ('C', 1, {'A': 0, 'B': 1})]
实现思路

为了解决这个问题,我们可以首先将电路图转换为一个由门对象组成的图形,并使用BFS或DFS算法访问输出门的所有输入门。 对于每个输入门,我们需要跟踪其值和值从哪里来。 我们可以使用Python的字典数据类型来存储门的值和输入门列表。

在这个过程中,我们还需要计算和存储门的真值表。这可以使用Python的eval()函数来实现。最后,我们可以使用这个真值表来计算门的值。

代码实现
def find_output_values(n, edges, defaults, inputs):
    from collections import deque
    
    # 将电路图转换为一个门对象的图形
    class Gate:
        def __init__(self, name, inputs, output):
            self.name = name
            self.inputs = inputs
            self.output = output
            self.value = None

    gates = {}
    for edge in edges:
        inputs = [gates.get(name, Gate(name, [], None)) for name in edge[:2]]
        output = gates.get(edge[2], Gate(edge[2], inputs, None))
        output.inputs += inputs
        gates[output.name] = output

    # 计算每个门的真值表
    for gate in gates.values():
        expr = "".join('(' + iv.name + ')' if isinstance(iv, Gate) else str(iv) for iv in gate.inputs)
        gate.truth_table = {}
        for i in range(2 ** len(gate.inputs)):
            inputs = {input.name: i >> idx & 1 for idx, input in enumerate(gate.inputs)}
            gate.truth_table[i] = int(eval(expr, {**defaults, **inputs}))
            
    # 计算所有输出门
    outputs = deque([output for output in gates.values() if not output.inputs])
    output_values = []
    while outputs:
        output = outputs.popleft()
        if output.value is None:
            inputs = {input.name: input.value for input in output.inputs}
            output.value = defaults.get(output.name, 0) if None in inputs.values() else output.truth_table[int(''.join(str(inputs[input.name]) for input in output.inputs), 2)]
            output_values.append((output.name, output.value, inputs))
        for input in output.inputs:
            if input.value is None:
                inputs = {input.name: input.value for input in input.inputs}
                input.value = defaults.get(input.name, 0) if None in inputs.values() else input.truth_table[int(''.join(str(inputs[input.name]) for input in input.inputs), 2)]
                outputs.append(input)

    return output_values    

代码中首先定义一个Gate类,表示每个门。 它有一个名称,一个输入门列表和一个输出值,以及它的真值表和值。 门的值是通过计算定义在truth_table字典中的真值表来计算的。

然后我们将输入边缘门添加到输出队列中,并重复计算所有输出门的值。 在这个过程中,我们使用Python的eval()函数计算每个门的真值表。 真值表是根据输入门列表中的值计算得出的。

一旦我们计算出一个门的值,就使用一个元组来记录该值,并将它的输入门添加到输出队列中以便于迭代两次计算。

最后返回所有输出门的值。