デジタルロジック回路-試験問題


14

試験で解決できなかった質問があります:

4ビットの数字を受信して​​いるデジタル論理回路を構築しtrue、数字が0である場合に返すか、7または14。私は一つだけ有するXORゲート(2つの入力)、1 NOR(3つの入力)、1 NAND(2つの入力)と1つの3対8デコーダ。

その質問は解決不可能だと思います。それを実現できる組み合わせは見つかりませんでした。それを解決する方法はありますか?


1
ヒントとして:4ビットと3-8デコーダーを考えると、ビットの1つを異なる方法で処理する必要があります。
ブライアンドラモンド

2
@BrianDrummondしかし、私はすでにそれを知っています、そして私はまだそれを解決することに成功しませんでした。私が試したすべてのソリューションは、ORゲートが1つ欠けていると感じています。問題を解決できる特定のゲートとそのような組み合わせを見つけることができません...タイプごとに1つのゲートしかないことに注意してください...
nrofis

3
@BrianDrummond:存在すると思われるソリューションの説明を投稿すると、それを検証できます。ソリューションが存在しないと言うことは困難ですが、ソリューションが有効であるかどうかを簡単に確認できます。
パサバポーaqui

2
@Ido Kessler ...私はあなたのソリューションに興味をそそられました。もしあなたの証明が正しければそれらを削除してすみません。今のところ誰も解決策がないようです。おそらく、アルゴリズムの説明を含めると、答えが改善されるでしょう。バグがなく、正しいことをどの程度自信がありますか?
ツタンカーメン

3
@jalalipop、昨日やった。イドケスラーとpasaba POR AQUIは右、私の教授は....質問が間違っていたとNANDがあるべきと述べたNORた
nrofis

回答:


24

これらのNor 3->1 Xor 2->1 Nand 2->1との可能な組み合わせをすべて試すアルゴリズムをC#で記述しましたDecoder 3->8

750万年 2時間実行した後、42 Falseを返しました。これは、このアルゴリズムがすべての可能な組み合わせをチェックするため、質問に答えがないことを証明していると思います。:)

私はそれを説明するように頼まれたので、次の部分はコードの部分の部分ごとの説明です。TL; DR-最後のコードまでスキップできます:)


入力ラインについて話しましょう。0または1の状態があり、可能な入力(0〜15)ごとに異なる値を保持します。

最初の行は次のようになります:0 1 0 1 0 1 ... 2番目は0 0 1 1 0 0 1 1 ... 3番目: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またはのようなbitLinesで論理要素を使用するたびに、Decoder実際に新しいbitLine \ sを作成しています。0から15までのすべての可能な入力の各行の値を知っているので、すべての可能な入力の新しいbitLine \ s値も計算できます!

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の動作を表します。

デコーダーの取り扱いは少し難しいですが、アイデアは「入力のビットが2進数で数値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;
}

これは、2つの行が等しいかどうかを確認するために使用する関数です。

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;
    }
}

この関数は、使用可能なbitLinesのリスト、リストの長さ、各要素が現在使用可能かどうかを表すブール値(xor / nor / nand / decoder)、および検索するbitLineを表す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も不可能であることに気付き、両方の答えを見つけることができませんでした。しかし、アルゴリズムは、手作業で解決策を見つけた上記のすべての場合にtrueを返しました。
イドケスラー

3
+1!@IdoKesslerでは、2ビット入力NANDを2ビット入力NORに変更して、ソフトウェアが解決するかどうかを確認できますか?実際、NANDの代わりにそのゲートで解決策があります。
ネクストハック

3
@私は、2ビットを使用するように変更したときに、それが真を返し、次-ハックNOR
イドケスラー

8

これは最も明白な解決策を破棄するための無回答です。

b1b2b4b8

b2b4

(nor {x=0,x=3,x=6}) nand (b2 xor b4)

b1b4b8 }、3-8デコーダーで実装されています。

ただし、前の式の簡略化は次のとおりです。

バツ=0 または バツ=3 または バツ=6 または b2=b4

それは予期されていません:

バツ=0 または バツ=3 または バツ=6 そして b2=b4

このため、「nand」ゲートは「nor」ゲートであるため、おそらく質問の間違いだと思います。


2
たぶんそれは本当です、私は答えを見つけることができませんでした。
nrofis

2
+1。私はあなたが正しいと信じています、そしてNANDはNORであるべきです。
ブライアンドラモンド

2

あなたの質問に対する有効な答えは、常に真を返す回路です。入力番号が0、7、または14の場合にもtrueを返すためです。

質問は、入力数が0、7、または14の場合にtrueを出力する回路を明示的に要求する必要があると思います。それ以外の場合はfalseを出力します。


2
うわー、私はそのような答えを期待していなかった。回路は...入力が0、7または14の場合にだけ、trueを返します
nrofis

1
そのように。
アグスティンテナ

2
仕様を注意深く見ると+1。このような仕様を顧客から取得する場合、これは悪いエンジニアリングです。その場合、正しい答えは、仕様に関する問題を顧客に指摘し、本当に欲しいものを確認することです。しかし、試験問題については、箱から出して考えることを示しており、非常に簡単な答えを正しく提供しています。
オリンラスロップ

-3

それは実行可能です。ヒントとして、中央の2ビットはこれらのビットパターンのすべてで等しいため、それらをxorすると0が生成され、他の2ビットでデコーダへの入力になります。残りのゲートは3つのデコーダー出力に適用され、正しいシングルビット出力を提供します。


すでにそれをやった。私は...疑問を解決するための任意の組み合わせを見つけることができませんでした
nrofis

xorを使用して、デコーダーの4ビットを3ビットに減らします。デコーダーには、3つの一致するパターンに対して1である3つの出力があります。また、それらを一緒にせず、ナンドゲートをインバータとして使用します。
ジョン

4
@John ...このソリューションでは、6つの製品用語(簡略化されていない)が得られますが、そのうち3つは無効です。言い換えると、ソリューションは0、7、または14に対してtrueを返しますが、また
ツタンカーメン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.