数字逻辑电路-考试题


14

考试中我有一个问题未能解决:

我需要建立正在接收4比特数和返回的数字逻辑电路true,如果数字是0714。我只有一个XOR门(2个输入),一个NOR(3个输入),一个NAND(2个输入)和一个3到8解码器。

我认为这个问题是无法解决的,我没有找到可以做到这一点的任何组合。知道如何解决吗?


1
提示:给定4位和3-8解码器,您必须区别对待其中一位。
Brian Drummond

2
@BrianDrummond,但是我已经知道了,但是我仍然没有成功解决它。我尝试过的每个解决方案都感觉缺少一个或门。我找不到与可以解决问题的给定门的这种组合...请注意,每种类型只有一个门...
nrofis

3
@BrianDrummond:如果您发布您认为存在的解决方案的描述,我们可以对其进行验证。很难说不存在解决方案,但是容易验证解决方案是否有效。
pasaba por aqui

2
@Ido Kessler ...我对您的解决方案很感兴趣,如果您的证明是正确的,对不起,您删除了它。到目前为止,似乎没有人有解决方案。也许,如果您包含算法的说明,它将改善答案。您对它的正确性和无缺陷性有多大信心?
Tut

3
@jalalipop,我昨天做了。Ido Kessler和pasaba por aqui是正确的,我的教授说这个问题是错误的,NAND应该是NOR
。...– nrofis

Answers:


24

我写在C#中的算法,尝试那些各种可能的组合Nor 3->1 Xor 2->1 Nand 2->1Decoder 3->8

在运行了7½百万年 2个小时之后,它返回了42 False。我相信这证明了这个问题没有答案,因为该算法会检查所有可能的组合。:)

我被要求描述它,因此下一部分是对代码各部分的解释,逐部分地进行解释。TL; DR-您只需跳到最后的代码即可:)


让我们谈谈输入线,它们具有0或1状态,对于每种可能的输入(0到15),它们具有不同的值:

对于第一行,它看起来像:0 1 0 1 0 1 ... ...第二个是:0 0 1 1 0 0 1 1 ...第三条:0 0 0 0 1 1 1 1 ....像二进制计数...你的主意:P

因此,我创建了一个代表每个状态下的每一行的对象:

class BitLine{
    bool[] IsActiveWhenInputIs = new bool[16];
}

就像说bitLine.IsActiveWhenInputIs [5]返回输入为5时该行是否处于活动状态。

这是一个完全创建输入行的代码:

var bitLineList = new BitLine[6]; // initialize new array of bitLines
for (int i = 0; i < 6; i++) bitLineList [i] = new BitLine(); // initialize each bitLine
for (int i = 0; i < 16; i++)
{
    for (int j = 0; j < 4; j++)
    {
        int checker = 1 << j; // check whether the j-th bit is activated in the binary representation of the number.
        bitLineList[j].IsActiveWhenInputIs[i] = ((checker & i) != 0); // if it's active, the AND result will be none zero, and so the return value will be true - which is what we need :D
    }
}

我们还将创建“始终为真”和“始终为假”位线-提供恒定的“ 0”输入或“ 1”输入。

for (int i = 0; i < 16; i++){
    bitLineList[4].IsActiveWhenInputIs[i] = false;
    bitLineList[5].IsActiveWhenInputIs[i] = true;
}

现在,如果您注意到了,我们正在寻找的实际上是一个特定的bitLine,当输入为0、7、14时,该位为true。在我们的类中表示它:

var neededBitLine = new BitLine();
for (int i = 0; i < 16; i++){
    neededBitLine.IsActiveWhenInputIs[i] = ((i % 7) == 0); // be true for any number that is devideble by 7 (0,7,14)
}

这使事情变得非常简单:我们实际上正在寻找的是一种从输入位线“伪造”此neededBitLine的方法(这就是我向程序表示希望输出的内容的方式)。

现在,这是我们如何去:每次我们使用一些逻辑元素在我们的位线,如时间XorNorNand甚至Decoder,我们实际上是在创建一个新的位线\ S。我们知道从0到15的每个可能输入中的每一行的值,因此我们也可以在每个可能的输入中计算新的bitLine的值!

Nand Nor和Xor都很简单:

void Xor(BitLine b1, BitLine b2, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = b1.IsActiveWhenInputIs[i] != b2.IsActiveWhenInputIs[i];
    }
}

void Nand(BitLine b1, BitLine b2, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] && b2.IsActiveWhenInputIs[i]);
    }
}

void Nor(BitLine b1, BitLine b2, BitLine b3, BitLine outputBitLine)
{
    for (var i = 0; i < 16; i++)
    {
        outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] || b2.IsActiveWhenInputIs[i] || b3.IsActiveWhenInputIs[i]);
    }
}

对于每个可能的输入,它表示新BitLine的行为。

处理解码器有点棘手,但想法是“如果输入的位代表二进制数x,则第x个输出位线将为true,而其他所有位将为false。与其他函数,这将获取一个位线数组,并向该数组添加8个新位线。

void Decoder(BitLine b1, BitLine b2, BitLine b3, List<BitLine> lines, int listOriginalLength)
{
    for (int optionNumber = 0; optionNumber < 8; optionNumber++)
    {
        for (var i = 0; i < 16; i++)
        {
            int sum = 0;
            if (b1.IsActiveWhenInputIs[i]) sum += 4;
            if (b2.IsActiveWhenInputIs[i]) sum += 2;
            if (b3.IsActiveWhenInputIs[i]) sum += 1;

            lines[listOriginalLength+optionNumber].IsActiveWhenInputIs[i] = (sum == optionNumber);
        }
    }
}

现在我们有了所有基本要素,下面让我们谈谈算法:

我们将要执行递归算法,在每个深度处,它将尝试在当前可用的位线上使用其他元素(nor \ nand \ xor \ decoder),然后将该元素设置为下一个递归深度不可用。每当我们到达底部并且没有更多要使用的元素时,我们都会检查是否有所需的位线。

此代码在任何给定时间检查当前行组是否包含我们要查找的行:

bool CheckIfSolutionExist(List<BitLine> lines, int linesLength BitLine neededLine)
{
    for(int i = 0; i<linesLength; i++){
         if (lines[i].CheckEquals(neededLine))
        {
            return true;
        }

    }
    return false;
}

该函数用于检查两行是否相等:

bool CheckEquals(BitLine other)
{
    for (var i = 0; i < 16; i++)
    {
        if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
        {
            return false;
        }
    }
    return true;
}

好的,所以现在是主要部分,这是主要算法:

bool Solve(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if ((!nand) && (!nor) && (!xor) && (!decoder))
    {
        return CheckIfSolutionExist(lines, listLength, neededLine);
    }
    else
    {
        if (HandleNand(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleNor(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleXor(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        if (HandleDecoder(lines, nand, nor, xor, decoder, neededLine,listLength))
        {
            return true;
        }
        return false;
    }
}

此函数接收可用位线的列表,列表长度,代表每个元素当前是否可用的布尔值(xor / nor / nand / decoder)以及代表我们要搜索的位线的bitLine。

在每个阶段,它都会检查是否还有其他要使用的元素,如果没有,它会检查是否存档所需的位线。

如果我们还有更多元素,那么对于每个元素,它都会调用一个函数,该函数应该使用这些元素来创建新的bitLines,然后再调用下一个递归深度。

下一个处理函数非常简单,可以将它们转换为“从可用位线中选择2 \ 3,然后使用相关元素进行组合。然后调用下一个递归深度,只是这次不包含递归这个元素!”。

这些是功能:

bool HandleNand(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (nand)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                BitLine.Nand(lines[i], lines[j],lines[listLength]);
                if (Solve(lines,listLength+1, false, nor, xor, decoder, neededLine))
                {
                    return true;
                }
            }
        }
    }
    return false;
}

bool HandleXor(List<BitLine> lines,  int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (xor)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                BitLine.Xor(lines[i], lines[j],lines[listLength]);
                if (Solve(lines,listLength+1, nand, nor, false, decoder, neededLine))
                {
                    return true;
                }

            }
        }
    }
    return false;
}

bool HandleNor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (nor)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                for (int k = j; k < listLength; k++)
                {
                    BitLine.Nor(lines[i], lines[j], lines[k],lines[listLength]);
                    if (Solve(lines,listLength+1, nand, false, xor, decoder, neededLine))
                    {
                        return true;
                    }

                }
            }
        }
    }
    return false;
}

bool HandleDecoder(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
{
    if (decoder)
    {
        for (int i = 0; i < listLength; i++)
        {
            for (int j = i; j < listLength; j++)
            {
                for (int k = j; k < listLength; k++)
                {
                    BitLine.Decoder(lines[i], lines[j], lines[k],lines,listLength);
                    if (Solve(lines,listLength+8, nand, nor, xor, false, neededLine))
                    {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

就是这样,我们只需要在所需的行中调用此函数,它就会检查电气部件的每种可能组合,以检查是否有可能以这样的方式将它们组合在一起:输出所需的值。

*请注意,我一直都使用相同的列表,因此无需一直创建新的位线实例。因此,我给它提供200的缓冲区。


这是完整的程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    public class BitLine
    {
        public bool[] IsActiveWhenInputIs = new bool[16];

        public static void Xor(BitLine b1, BitLine b2, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = b1.IsActiveWhenInputIs[i] != b2.IsActiveWhenInputIs[i];
            }
        }

        public static void Nand(BitLine b1, BitLine b2, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] && b2.IsActiveWhenInputIs[i]);
            }
        }

        public static void Nor(BitLine b1, BitLine b2, BitLine b3, BitLine outputBitLine)
        {
            for (var i = 0; i < 16; i++)
            {
                outputBitLine.IsActiveWhenInputIs[i] = !(b1.IsActiveWhenInputIs[i] || b2.IsActiveWhenInputIs[i] || b3.IsActiveWhenInputIs[i]);
            }
        }

        public static void Decoder(BitLine b1, BitLine b2, BitLine b3, List<BitLine> lines, int listOriginalLength)
        {
            for (int optionNumber = 0; optionNumber < 8; optionNumber++)
            {
                for (var i = 0; i < 16; i++)
                {
                    int sum = 0;
                    if (b1.IsActiveWhenInputIs[i]) sum += 4;
                    if (b2.IsActiveWhenInputIs[i]) sum += 2;
                    if (b3.IsActiveWhenInputIs[i]) sum += 1;

                    lines[listOriginalLength + optionNumber].IsActiveWhenInputIs[i] = (sum == optionNumber);
                }
            }
        }

        public bool CheckEquals(BitLine other)
        {
            for (var i = 0; i < 16; i++)
            {
                if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
                {
                    return false;
                }
            }
            return true;
        }

    }

    public class Solver
    {
        bool CheckIfSolutionExist(List<BitLine> lines, int linesLength, BitLine neededLine)
        {
            for (int i = 0; i < linesLength; i++)
            {
                if (lines[i].CheckEquals(neededLine))
                {
                    return true;
                }

            }
            return false;
        }

        bool HandleNand(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (nand)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        BitLine.Nand(lines[i], lines[j], lines[listLength]);
                        if (Solve(lines, listLength + 1, false, nor, xor, decoder, neededLine))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        bool HandleXor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (xor)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        BitLine.Xor(lines[i], lines[j], lines[listLength]);
                        if (Solve(lines, listLength + 1, nand, nor, false, decoder, neededLine))
                        {
                            return true;
                        }

                    }
                }
            }
            return false;
        }

        bool HandleNor(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (nor)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        for (int k = j; k < listLength; k++)
                        {
                            BitLine.Nor(lines[i], lines[j], lines[k], lines[listLength]);
                            if (Solve(lines, listLength + 1, nand, false, xor, decoder, neededLine))
                            {
                                return true;
                            }

                        }
                    }
                }
            }
            return false;
        }

        bool HandleDecoder(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if (decoder)
            {
                for (int i = 0; i < listLength; i++)
                {
                    for (int j = i; j < listLength; j++)
                    {
                        for (int k = j; k < listLength; k++)
                        {
                            BitLine.Decoder(lines[i], lines[j], lines[k], lines, listLength);
                            if (Solve(lines, listLength + 8, nand, nor, xor, false, neededLine))
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }

        public bool Solve(List<BitLine> lines, int listLength, bool nand, bool nor, bool xor, bool decoder, BitLine neededLine)
        {
            if ((!nand) && (!nor) && (!xor) && (!decoder))
            {
                return CheckIfSolutionExist(lines, listLength, neededLine);
            }
            else
            {
                if (HandleNand(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleNor(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleXor(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                if (HandleDecoder(lines, listLength, nand, nor, xor, decoder, neededLine))
                {
                    return true;
                }
                return false;
            }
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            List<BitLine> list = new List<BitLine>();
            var bitLineList = new BitLine[200];
            for (int i = 0; i < 200; i++) bitLineList[i] = new BitLine();

            // set input bit:
            for (int i = 0; i < 16; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    int checker = 1 << j;
                    bitLineList[j].IsActiveWhenInputIs[i] = ((checker & i) != 0);
                }
            }

            // set zero and one constant bits:
            for (int i = 0; i < 16; i++)
            {
                bitLineList[4].IsActiveWhenInputIs[i] = false;
                bitLineList[5].IsActiveWhenInputIs[i] = true;
            }

            list.AddRange(bitLineList);

            var neededBitLine = new BitLine();
            for (int i = 0; i < 16; i++)
            {
                neededBitLine.IsActiveWhenInputIs[i] = (i%7==0); // be true for any number that is devideble by 7 (0,7,14)
            }

            var solver = new Solver();
            Console.WriteLine(solver.Solve(list, 6, true, true, true, true, neededBitLine));
            Console.ReadKey();
        }
    }
}

希望这次是一个有效的解释:P


6
您可能需要对这种求解器的工作方式进行高级描述。通过阅读这个完全没有注释的代码转储,这并不是立即显而易见的。
戴夫·特威德

2
这是一个有趣的解决方案,希望您能提供该算法的描述。您是否做过类似的测试案例以证明该方法?(顺便说一句,我喜欢微妙的道格拉斯·亚当斯参考)
Tut

2
我将添加我可以通过一些测试用例尝试该算法:x == 2,x == 3,x == 4,...,x == 11。由于运行时间很长,因此我注意到x%3 == 0和x%5 == 0可能也是不可能的,而我都找不到答案。但是,对于上述所有情况,该算法都返回了真值,而我为它们手工找到了解决方案。
伊多·凯斯勒

3
+1!@IdoKessler您可以尝试将2位输入NAND更改为2位输入NOR,并检查您的软件是否提供了解决方案?实际上,有了该门而不是NAND,就有了解决方案。
next-hack

3
@ next-hack,当我将其更改为使用2位NOR时,它返回True
Ido Kessler

8

这是一个无法回答的问题,它会放弃最明显的解决方案。

b1个b2b4b8

b2b4

也不 {X=0X=3X=6} 南德 b2 异或 b4

其中x是{ b1个b4b8 },使用3-8解码器实现。

但是,先前表达式的简化为:

X=0 要么 X=3 要么 X=6 要么 b2=b4

那不是预期的:

X=0 要么 X=3 要么 X=6  b2=b4

因此,我认为该问题可能是一个错误,因为“ nand”表示“ no”。


2
也许是这样,我没有找到答案。
nrofis

2
+1。我相信您是对的,NAND应该是NOR。
Brian Drummond

2

对您的问题的有效答案将是任何始终返回true的电路。因为如果输入数字是0,7或14,也会返回true。

我认为这个问题应该明确要求一个电路,如果输入数字是0,7或14,则输出为true。否则输出false。


2
哇,没想到会有这样的答案。仅当输入为
0、7

1
完全一样。
奥古斯丁·泰纳

2
+1以仔细查看规格。从客户那里获得这种规格时,这是一项糟糕的工程。在这种情况下,正确的答案是向客户指出规格问题,并验证他们真正想要的是什么。但是,对于考试题,它显示了开箱即用的思维方式,并且正确地提供了一个非常简单的答案。
奥林·拉斯洛普

-3

这是可行的。提示中间的两位对于所有这些位模式都是相等的,因此对它们进行异或运算将产生0,然后可以将其与其他两位一起作为解码器的输入。其余的门将施加到三个解码器输出,以提供正确的一位输出。


已经做到了。我没有找到能解决问题的任何组合……
nrofis

使用xor将解码器的4位减少为3位。解码器将具有三个输出,三个匹配模式的输出为1。它们也不能一起使用,并且将nand门用作反相器。
约翰·约翰·约翰(John

4
@John ...您的解决方案产生6个乘积项(未简化),其中3个无效。换句话说,尽管您的解决方案对于0、7或14返回true;它也为1,6或8,返回true
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.