Sayısal Mantık devresi - sınav sorusu


14

Sınavdan çözemediğim bir sorum var:

Ben 4 bit sayı almak ve truesayı ise döndüren bir dijital mantık devresi inşa etmek gerekir 0, 7veya 14. Sadece bir XORkapı (2 giriş), bir NOR(3 giriş), bir NAND(2 giriş) ve bir 3 ila 8 dekoderi var.

Bence bu soru çözümsüz, bunu yapabilecek bir kombinasyon bulamadım. Nasıl çözüleceği hakkında bir fikrin var mı?


1
Bir ipucu olarak: 4 bit ve 3-8 kod çözücü verildiğinde, bitlerden birine farklı davranmanız gerekir.
Brian Drummond

2
@BrianDrummond ama bunu zaten biliyorum ve hala çözmeyi başaramadım. Denediğim her çözüm, bir VEYA geçidi eksik olduğunu hissediyor. Sorunu çözebilecek verilen kapılarla böyle bir kombinasyon
bulamıyorum

3
@BrianDrummond: Var olduğunu düşündüğünüz çözümün bir açıklamasını gönderirseniz, bunu doğrulayabiliriz. Herhangi bir çözümün mevcut olmadığını söylemek zordur, ancak bir çözümün geçerli olup olmadığını doğrulamak kolaydır.
pasaba por aqui

2
@Ido Kessler ... Çözümünüzün ilgisini çekmiştim ve kanıtınız doğruysa sildiğiniz için üzgünüm. Şimdiye kadar hiç kimsenin bir çözümü yok gibi görünüyor. Belki de algoritmanızın bir açıklamasını eklerseniz, bu cevap daha iyi olur. Doğru ve hatasız olduğundan ne kadar eminsiniz?
Tut

3
@jalalipop, dün yaptım. Ido Kessler ve pasaba por aqui haklıydı, profesörüm sorunun yanlış olduğunu ve
NAND'ın

Yanıtlar:


24

C # 'da bu olası her kombinasyonu deneyen bir algoritma yazdım Nor 3->1 Xor 2->1 Nand 2->1ve Decoder 3->8.

7½ milyon yıl 2 saat çalıştırdıktan sonra 42 False geri döndü . İnanıyorum ki, bu algoritma olası her kombinasyonu kontrol ettiği için sorunun cevabı olmadığını kanıtlıyor. :)

Bunu açıklamam istendi, bu yüzden bir sonraki kısım, kod bölümlerinin bir kısmı, bir kısmı. TL; DR - en sonunda koda atlayabilirsiniz :)


Girdi satırları hakkında konuşalım, 0 veya 1 durumları var ve olası girişlerin (0 ila 15) her biri için farklı değerler tutuyorlar:

ilk satır için şu şekilde görünür: 0 1 0 1 0 1 ... İkincisi: 0 0 1 1 0 0 1 1 ... üçüncü: 0 0 0 0 1 1 1 .... gibi ikili sayıyor ... fikri anladınız: P

Bu yüzden her eyaletindeki her satırı temsil eden bir nesne yarattım:

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

Dediği gibi bitLine.IsActiveWhenInputIs [5] giriş 5 iken hattın aktif olup olmadığını döndürür.

Bu, girdi satırlarını tamamen oluşturan bir koddur:

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

Sabit "0" giriş veya "1" giriş sağlamak için "her zaman doğru" ve "her zaman yanlış" bit çizgileri de oluşturacağız.

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

Şimdi fark ederseniz, aradığımız aslında belirli bir bitLine'dir, giriş 0, 7, 14 olduğunda doğrudur. Bunu sınıfımızda temsil edelim:

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

Bu işleri gerçekten basitleştirdi: aradığımız şey, bu bitBitLine'ı girdi bit satırından "taklit etmenin" bir yoludur (bu benim programım için çıktımın olmasını istediğim şeyi temsil ediyorum).

Biz gitmek ne kadar şimdi, şudur: biz gibi bizim bitLines bazı mantıksal eleman her kullandığınızda Xor, Nor, Nandhatta Decoder, aslında yeni bir bitLine yaratıyor \ s. Olası her girişteki her bir satırın değerini 0 ila 15 arasında biliyoruz, böylece yeni bitLine \ s değerini olası her girişte de hesaplayabiliriz!

Nand Nor ve Xor'un hepsi açıktır:

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

Olası her giriş için, yeni BitLine'ın nasıl davranacağını temsil eder.

Kod çözücüyü kullanmak biraz zordur, ancak fikir "girişteki bitler ikilikteki x sayısını temsil ediyorsa, x-çıkış çıkış bit çizgisi doğru olurken, diğerleri yanlış olacaktır. işlevinde, bu bir dizi bitline alır ve diziye 8 yeni bitline ekler.

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

Şimdi tüm temel unsurlarımız var, bu yüzden algoritma hakkında konuşalım:

Yinelenen bir algoritma yapacağız, her derinlikte şu anda mevcut olan bit satırlarında başka bir öğe (ne de \ nand \ xor \ dekoder) kullanmaya çalışacak ve ardından öğeyi bir sonraki özyinelemeli derinlik için kullanılamayacak şekilde ayarlayacağız. Ne zaman dibe vardığımızda ve kullanacak başka elementimiz olmadığında, aradığımız şey olan bir bit çizgisine sahip olup olmadığımızı kontrol edeceğiz.

Bu kod, geçerli satır grubunun aradığımız satırı içerip içermediğini herhangi bir zamanda kontrol eder:

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

İki satırın eşit olup olmadığını kontrol etmek için kullandığı işlev budur:

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

Tamam, şimdi ana bölüm için bu ana algoritma:

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

Bu işlev, kullanılabilir bitLines'ın bir listesini, liste uzunluğunu, her bir öğenin o anda kullanılabilir olup olmadığını gösteren bir boole (xor / nor / nand / decoder) ve aradığımız bitLine'i temsil eden bir bitLine alır.

Her aşamada, kullanılacak daha fazla unsurumuz olup olmadığını kontrol eder, eğer değilse - gerekli bit çizgimizi arşivleyip arşivlemediğimizi kontrol eder.

Hala daha fazla öğemiz varsa, bu nedenle her öğe için bu öğeleri kullanarak yeni bitLines oluşturma ve daha sonra bir sonraki yinelenen derinliği çağırmayı gerektiren bir işlevi çağırır.

Bir sonraki işleyici işlevlerinin hepsi oldukça basittir, kullanılabilir bit çizgilerinden "2 \ 3 seçin ve ilgili öğeyi kullanarak birleştirin. Sonra özyinelemenin bir sonraki derinliğini çağırın, sadece bu sefer bu eleman! "

bunlar fonksiyonlar:

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

Ve işte bu, sadece bu işlevi aradığımız hatla çağırıyoruz ve onları tek bir hat olacak şekilde birleştirmenin mümkün olup olmadığını kontrol etmek için elektrik parçalarının olası her kombinasyonunu kontrol ediyor. gerekli değerlerle çıktılanır.

* her zaman aynı listeyi kullandığımı fark ettim, bu yüzden her zaman yeni bitlines örnekleri oluşturmam gerekmeyecek. Bu nedenle 200 tamponlu veriyorum.


Bu tam program:

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

Umarım bu sefer geçerli bir açıklamadır: P


6
Bu tür bir çözücünün nasıl çalıştığına dair üst düzey bir açıklama eklemek isteyebilirsiniz. Bu tamamen önerilmeyen kod dökümünü okumak hemen belli değil.
Dave Tweed

2
Bu ilginç bir çözüm ve umarım algoritmanın bir tanımını verebilirsiniz. Yöntemi kanıtlamak için benzer bir test örneği yaptınız mı? (BTW, ince Douglas Adams referansını seviyorum)
Tut

2
Kontrol edebileceğim bazı test durumuyla bu algoritmayı denediğimi ekleyeceğim: x == 2, x == 3, x == 4, ..., x == 11. Çalışması uzun zaman aldığından, x% 3 == 0 ve x% 5 == 0'ın da imkansız olabileceğini fark ettim ve her ikisine de bir cevap bulamadım. Ancak algoritma, elle bir çözüm bulduğum yukarıdaki tüm durumlar için doğru döndü.
Ido Kessler

3
1! @IdoKessler, 2 bit giriş NAND'sini 2 bit giriş NOR ile değiştirmeyi deneyebilir ve yazılımınızın bir çözüm sağlayıp sağlamadığını kontrol edebilir misiniz? Aslında, bu kapı ile bir NAND yerine bir çözüm var.
sonraki

3
@ next-hack 2 bitlik bir NOR kullanmak için değiştirdiğimde True döndürdü
Ido Kessler

8

Bu, en bariz çözümü atmak için bir cevap değildir.

b1b2b4b8

b2b4

(ne de {x=0,x=3,x=6}) nAND (b2 xor b4)

b1b4b8

Bununla birlikte, önceki ifadenin basitleştirilmesi:

(x=0 veya x=3 veya x=6) veya (b2=b4)

bu beklenen değil:

(x=0 veya x=3 veya x=6) ve (b2=b4)

Bu nedenle, soruda "nand" kapısı "ne de" bir hata olabileceğini düşünüyorum.


2
Belki bu doğrudur, ben de cevap bulamadım.
nrofis

2
+1. Haklı olduğuna inanıyorum ve NAND bir NOR olmalı.
Brian Drummond

2

Sorunuza geçerli bir cevap, her zaman doğru olan herhangi bir devre olacaktır. Çünkü giriş sayıları 0,7 veya 14 ise doğru dönecektir.

Sorunun, giriş sayıları 0,7 veya 14 ise çıkışların doğru olduğu ve aksi halde yanlış çıktığı bir devre sorması gerektiğini düşünüyorum.


2
Wow, böyle bir cevap beklemiyordum. Devre yalnızca giriş 0, 7 veya 14 ise doğrudur.
nrofis 19:17

1
Tam da böyle.
Agustin Tena

2
Özelliklere dikkatlice bakmak için +1. Bir müşteriden böyle bir spesifikasyon alırken bu kötü bir mühendisliktir. Bu durumda, doğru cevap, spesifikasyondaki sorunu müşteriye işaret etmek ve gerçekten ne istediklerini doğrulamaktır. Ancak, bir sınav sorusu için kutunun dışında düşünmeyi gösterir ve çok basit bir cevap verir.
Olin Lathrop

-3

Bu yapılabilir. Bir ipucu olarak, ortadaki iki bit, tüm bu bit desenleri için eşittir, bu nedenle onları ayırmak, daha sonra diğer iki bitle dekodere bir girdi olabilecek 0 üretecektir. Kalan kapılar, doğru tek bit çıkışını sağlamak için üç dekoder çıkışına uygulanır.


Bunu zaten yaptım. Soruyu çözen bir kombinasyon bulamadım ...
nrofis

Kod çözücü için dört biti üç bite düşürmek için xor kullanın. Kod çözücü, eşleşen üç desen için 1 olan üç çıkışa sahip olacaktır. Ne de birlikte ve nand geçidi invertör olarak kullanın.
John

4
@John ... Çözümünüz, 3 tanesi geçersiz olmak üzere 6 ürün terimi (sadeleştirilmemiş) veriyor. Diğer bir deyişle, çözümünüz 0, 7 veya 14 için geçerli olsa da; 1, 6 veya 8 için de geçerli.
Tut
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.