Цифрова логічна схема - екзаменаційне питання


14

У мене є питання з іспиту, який не вдалося вирішити:

Мені потрібно побудувати цифрову логічну схему, яка отримує 4-бітове число і повертається, trueякщо число є 0, 7або 14. У мене є лише один XORзатвор (2 входи), один NOR(3 входи), один NAND(2 входи) і один декодер 3 на 8.

Я думаю, що це питання нерозв'язне, я не знайшов жодної комбінації, яка могла б це зробити. Будь-яка ідея, як її вирішити?


1
Як підказка: якщо ви маєте 4 біти і 3-8 декодера, ви повинні по-різному ставитися до одного з бітів.
Брайан Драммонд

2
@BrianDrummond, але я це вже знаю, і мені все-таки не вдалося вирішити це. Кожне рішення, яке я спробував, відчуває, що в ньому відсутня одна АБО ворота. Я не можу знайти таке поєднання із даними воротами, які можуть вирішити проблему ... Зауважте, що у мене є лише
ОДНІ

3
@BrianDrummond: якщо ви опублікуєте опис рішення, яке, на вашу думку, існує, ми можемо його перевірити. Важко сказати, що рішення не існує, але легко перевірити, чи рішення є дійсним.
pasaba por aqui

2
@ Ido Kessler ... Мене заінтригувало ваше рішення, і якщо ваше підтвердження їх правильне, вибачте, що ви його видалили. Ніхто поки що, здається, не має рішення. Можливо, якби ви включили опис свого алгоритму, це поліпшить відповідь. Наскільки ви впевнені, що це правильно та без помилок?
Поне

3
@jalalipop, я вчора. Ідо Кесслер і pasaba por aqui мали рацію, мій професор сказав, що питання було неправильним і NAND повинен бути NOR ....
nrofis

Відповіді:


24

Я написав алгоритм в C #, який намагається використовувати всі можливі комбінації цих Nor 3->1 Xor 2->1 Nand 2->1і Decoder 3->8.

Провівши її протягом 7½ мільйонів років 2 години, він повернувся 42 Неправдивими. Я вважаю, що це доводить, що на запитання немає відповіді, оскільки цей алгоритм перевіряє всі можливі комбінації. :)

Мене попросили описати, тому наступна частина - це пояснення частин коду, частина за частиною. 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. Давайте представимо це у нашому класі:

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

Це зробило речі дуже простими: те, що ми насправді шукаємо, - це спосіб «підробити» цей необхіднийBitLine з вхідного бітового рядка (саме так я представляю своїй програмі те, що я хочу, щоб мій результат був).

Тепер, це те , як ми йдемо далі: кожен раз , коли ми використовуємо певний логічний елемент на нашому bitLines як Xor, Nor, Nandабо навіть Decoder, ми на самому ділі створюємо новий bitLine \ с. Ми знаємо значення кожного рядка на кожному можливому вході від 0 до 15, тому ми можемо обчислити нове значення bitLine \ s і на кожному можливому введенні!

Нанд Нор і 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-й вихідний бітовий рядок буде істинним, тоді як всі інші будуть помилковими. На відміну від інших Функція, ця отримує масив біткоїни, і додайте до масиву 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);
        }
    }
}

Тепер у нас є всі наші основні елементи, тому поговоримо про алгоритм:

Ми будемо робити рекурсивний алгоритм, на кожній глибині він намагатиметься використовувати інші елементи (ні \ 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 / декодер), і bitLine, що представляє бітLine, який ми шукаємо.

На кожному етапі він перевіряє, чи є у нас ще якісь елементи для використання, якщо ні - перевіряє, чи ми архівуємо потрібний біткойн.

Якщо у нас ще є більше елементів, то для кожного елемента він викликає функцію, яка повинна обробляти створення нових біт-ліній за допомогою цих елементів і викликати наступну рекурсивну глибину.

У наступних функціях обробника все досить просто, їх можна перекласти на "вибрати 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
Це інтригуюче рішення, і я сподіваюся, що ви можете надати опис алгоритму. Ви робили якісь подібні тестові випадки, щоб довести метод? (До речі, я , як тонкий Дуглас Адамс посилання)
Тута

2
Додам, що я спробував цей алгоритм з деяким тестовим випадком, який я міг перевірити: x == 2, x == 3, x == 4, ..., x == 11. Оскільки це запускає багато часу, я помічаю, що x% 3 == 0 і x% 5 == 0 також можуть бути неможливими, і я не зміг знайти відповіді на обидва. Але алгоритм повернув істину для всіх вищезазначених випадків, для яких я знайшов рішення вручну.
Ідо Кесслер

3
+1! @IdoKessler чи можете ви спробувати змінити 2-бітний вхідний NAND на 2-бітний вхід NOR і перевірити, чи програмне забезпечення дає рішення? Насправді, із цією брамою, замість NAND, є рішення.
наступний хак

3
@ next-hack повернувся True, коли я змінив його на 2-бітний NOR
Ido Kessler

8

Це невідповідь, щоб відмовитись від найбільш очевидного рішення.

б1б2б4б8

б2б4

(ні {х=0,х=3,х=6}) нанд (б2 xor б4)

б1б4б8

Однак спрощення попереднього виразу:

(х=0 або х=3 або х=6) або (б2=б4)

це не очікуване:

(х=0 або х=3 або х=6) і (б2=б4)

З цієї причини, я вважаю, ймовірна помилка у питанні, будучи "nand" воротами "ні".


2
Можливо, це правда, я так і не знайшов відповіді.
nrofis

2
+1. Я вважаю, що ти маєш рацію, і NAND повинен бути НОР.
Брайан Драммонд

2

Важливою відповіддю на ваше запитання буде будь-яка схема, яка повертається завжди правдивою. Тому що він повернеться істинним також, якщо вхідні числа будуть 0,7, або 14.

Я думаю, що питання має чітко запитувати схему, яка виводить істину, якщо вхідні числа дорівнюють 0,7, або 14. І це виводить помилкові помилки.


2
Нічого собі, я не очікував такої відповіді. Схема повинна повернути істину тоді і лише тоді, коли вхід 0, 7 або 14 ...
nrofis

1
точно так.
Августин Тена

2
+1 за уважний огляд специфікацій. Це погана інженерія при отриманні такої специфікації від замовника. У цьому випадку правильною відповіддю є вказати на проблему із специфікацією замовнику та перевірити, чого він насправді хоче. Але на екзаменаційне запитання він відображає роздуми поза коробкою, і це правильно дає дуже просту відповідь.
Олін Латроп

-3

Це можливо. Як підказка, середні два біти рівні для всіх цих бітових шаблонів, тому їх зчеплення виробить 0, що потім може бути входом до декодера з двома іншими бітами. Решта затворів застосовуються до трьох виходів декодера, щоб забезпечити правильний вихід одного біта.


Вже зробив це. Я не знайшов жодної комбінації, яка вирішила б питання ...
nrofis

Використовуйте xor, щоб зменшити чотири біти до трьох біт для декодера. Декодер матиме три виходи, які є 1 для трьох узгоджених шаблонів. Не використовуйте їх разом і використовуйте нанду в якості інвертора.
Джон

4
@John ... Ваше рішення дає 6 термінів продукту (не спрощені), 3 з яких недійсні. Іншими словами, хоча ваше рішення повертає істину для 0, 7 або 14; воно також повертає істину для 1, 6 або 8.
Початок
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.