Tengo una pregunta del examen que no pude resolver:
Necesito construir un circuito lógico digital que reciba un número de 4 bits y regrese true
si el número es 0
, 7
o 14
. Solo tengo una XOR
puerta (2 entradas), una NOR
(3 entradas), una NAND
(2 entradas) y un decodificador de 3 a 8.
Creo que esa pregunta no tiene solución, no encontré ninguna combinación que pueda hacer eso. ¿Alguna idea de cómo solucionarlo?
Escribí un algoritmo en C# que prueba todas las combinaciones posibles de esos Nor 3->1
Xor 2->1
Nand 2->1
y Decoder 3->8
.
Después de ejecutarlo durante 7½ millones de años 2 horas, devolvió 42 Falso. Creo que esto prueba que la pregunta no tiene respuesta ya que este algoritmo verifica todas las combinaciones posibles. :)
Me pidieron que lo describiera, por lo que la siguiente parte es una explicación de las partes del código, parte por parte. TL; DR : puede saltar al código al final :)
Hablemos de las líneas de entrada, tienen estados 0 o 1 y para cada una de las entradas posibles (0 a 15) tienen valores diferentes:
para la primera línea se ve así: 0 1 0 1 0 1 ... El segundo es: 0 0 1 1 0 0 1 1 ... el tercero: 0 0 0 0 1 1 1 1 .... como binario contando... ya entendiste :P
Entonces creé un objeto que representa cada línea en cada uno de sus estados:
class BitLine{
bool[] IsActiveWhenInputIs = new bool[16];
}
Como dice, bitLine.IsActiveWhenInputIs[5] devuelve si la línea estaba activa cuando la entrada era 5.
Este es un código que crea las líneas de entrada por completo:
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
}
}
También crearemos líneas de bit "siempre verdadero" y "siempre falso" para proporcionar una entrada constante "0" o "1".
for (int i = 0; i < 16; i++){
bitLineList[4].IsActiveWhenInputIs[i] = false;
bitLineList[5].IsActiveWhenInputIs[i] = true;
}
Ahora, si nota, lo que estamos buscando es en realidad una línea de bits específica, una que sea verdadera cuando la entrada sea 0, 7, 14. Representémosla en nuestra clase:
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)
}
Esto simplificó las cosas: lo que en realidad estamos buscando es una forma de "forjar" este BitLine necesario a partir de la línea de bits de entrada (así es como represento en mi programa lo que quiero que sea mi salida).
Ahora, así es como continuamos: cada vez que usamos algún elemento lógico en nuestras líneas de bits como Xor
, o incluso el Nor
, en realidad estamos creando una nueva línea de bits. ¡Conocemos el valor de cada una de las líneas en cada entrada posible de 0 a 15, por lo que también podemos calcular el valor de la nueva línea de bits en cada entrada posible!Nand
Decoder
Nand Nor y Xor son sencillos:
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]);
}
}
Para cada entrada posible, representa cómo actuará el nuevo BitLine.
Manejar el decodificador es un poco complicado, pero la idea es "si los bits en la entrada representan el número x en binario, entonces la línea de bits de salida x-ésima será verdadera, mientras que todas las demás serán falsas. A diferencia de la otra función, esta obtiene una matriz de líneas de bits y agrega 8 líneas de bits nuevas a la matriz.
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);
}
}
}
Ahora que tenemos todos nuestros elementos básicos, hablemos del algoritmo:
Vamos a hacer un algoritmo recursivo, en cada profundidad intentará usar otros elementos (nor\nand\xor\decoder) en las líneas de bits disponibles actualmente, y luego configurará el elemento como inutilizable para la siguiente profundidad recursiva. Siempre que lleguemos al fondo y no tengamos más elementos para usar, comprobaremos si tenemos una línea de bits que es la que buscábamos.
Este código verifica en cualquier momento si el grupo actual de líneas contiene la línea que estamos buscando:
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;
}
Esta es la función que utiliza para verificar si dos líneas son iguales:
bool CheckEquals(BitLine other)
{
for (var i = 0; i < 16; i++)
{
if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
{
return false;
}
}
return true;
}
Ok, ahora la parte principal, este es el algoritmo principal:
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;
}
}
Esta función recibe una lista de las líneas de bits disponibles, la longitud de la lista, un valor booleano que representa si cada elemento está actualmente disponible (xor/nor/nand/decodificador) y una línea de bits que representa la línea de bits que estamos buscando.
En cada etapa, verifica si tenemos más elementos para usar, si no, verifica si archivamos nuestra línea de bits necesaria.
Si todavía tenemos más elementos, entonces para cada elemento llama a una función que se supone que maneja la creación de nuevas líneas de bits usando esos elementos y luego llama a la siguiente profundidad recursiva.
Las siguientes funciones del controlador son bastante sencillas, se pueden traducir a "elegir 2\3 de las líneas de bits disponibles y combinarlas usando el elemento relevante. Luego llame a la siguiente profundidad de la recursividad, solo que esta vez no contendrá este elemento!".
esas son las funciones:
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;
}
Y esto es todo, simplemente llamamos a esta función con la línea necesaria que estamos buscando, y verifica todas las combinaciones posibles de las partes eléctricas para verificar si es posible combinarlas de tal manera que al final quede una sola línea. salida con los valores necesarios.
*Tenga en cuenta que uso la misma lista todo el tiempo, por lo que no tendré que crear nuevas instancias de líneas de bits todo el tiempo. Le doy un buffer de 200 por esa razón.
Este es el programa completo:
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();
}
}
}
Espero que esta vez sea una explicación válida :P
Esta es una no respuesta, para descartar la solución más obvia.
Numeraré los bits por su peso: , , y .
como bits y son iguales en todos los números válidos, podríamos pensar en implementar la expresión lógica:
donde x es { , , }, implementado con el decodificador 3-8.
Sin embargo, la simplificación de la expresión anterior es:
eso no es lo esperado:
Por esta razón, creo probable un error en la pregunta, siendo la puerta "nand" una puerta "ni".
Una respuesta válida a su pregunta sería cualquier circuito que siempre sea verdadero. Porque también devolverá verdadero si los números de entrada son 0,7 o 14.
Creo que la pregunta debería pedir explícitamente un circuito que dé como resultado verdadero si los números de entrada son 0,7 o 14. Y que dé como resultado falso de lo contrario.
es factible Como sugerencia, los dos bits del medio son iguales para todos estos patrones de bits, por lo que al eliminarlos producirá 0, que luego puede ser una entrada al decodificador con los otros dos bits. Las puertas restantes se aplican a las tres salidas del decodificador para proporcionar la salida correcta de un solo bit.
usuario_1818839
nrofis
usuario_1818839
nrofis
nrofis
nrofis
pasaba por aqui
Gesto de desaprobación
nrofis
Gesto de desaprobación
nrofis
jalalipop
nrofis