Tôi đã viết một thuật toán trong C # để thử mọi sự kết hợp có thể có của chúng Nor 3->1
Xor 2->1
Nand 2->1
và Decoder 3->8
.
Sau khi chạy nó 7 triệu năm 2 giờ, nó trả về 42 Sai. Tôi tin rằng điều này dự đoán rằng câu hỏi không có câu trả lời vì thuật toán này kiểm tra mọi sự kết hợp có thể. :)
Tôi đã được yêu cầu mô tả nó, vì vậy phần tiếp theo là một lời giải thích về các phần của mã, từng phần. TL; DR - bạn chỉ có thể bỏ qua phần mã ở cuối :)
Hãy nói về các dòng đầu vào, chúng có 0 hoặc 1 trạng thái và với mỗi đầu vào có thể (0 đến 15) chúng giữ các giá trị khác nhau:
đối với dòng đầu tiên, nó trông như thế: 0 1 0 1 0 1 ... Dòng thứ hai là: 0 0 1 1 0 0 1 1 ... thứ ba: 0 0 0 0 1 1 1 1 .... như nhị phân đếm ... bạn có ý tưởng: P
Vì vậy, tôi đã tạo một đối tượng đại diện cho từng dòng trong mỗi trạng thái của mình:
class BitLine{
bool[] IsActiveWhenInputIs = new bool[16];
}
Như nó nói bitLine.IsActiveWhenInputIs [5] trả về việc dòng có hoạt động khi đầu vào là 5 hay không.
Đây là mã tạo ra các dòng đầu vào hoàn toàn:
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
}
}
Chúng tôi cũng sẽ tạo ra một dòng bit "luôn luôn đúng" và "luôn luôn sai" - để cung cấp đầu vào "0" hoặc đầu vào "1" không đổi.
for (int i = 0; i < 16; i++){
bitLineList[4].IsActiveWhenInputIs[i] = false;
bitLineList[5].IsActiveWhenInputIs[i] = true;
}
Bây giờ nếu bạn chú ý, những gì chúng ta đang tìm kiếm thực sự là một bitLine cụ thể, một điều đúng khi đầu vào là 0, 7, 14. Hãy trình bày nó trong lớp của chúng ta:
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)
}
Điều này làm cho mọi thứ thực sự đơn giản: những gì chúng ta thực sự đang tìm kiếm là một cách để "giả mạo" cái này cần thiết từ dòng bit đầu vào (đây là cách tôi thể hiện cho chương trình của mình những gì tôi muốn đầu ra của mình).
Bây giờ, đây là cách chúng tôi đi trên: mỗi lần chúng tôi sử dụng một số yếu tố logic trên bitlines của chúng tôi như Xor
, Nor
, Nand
hoặc thậm chí Decoder
, chúng tôi đang thực sự tạo ra một bitLine mới \ s. Chúng tôi biết giá trị của từng dòng trong mỗi đầu vào có thể từ 0 đến 15, vì vậy chúng tôi cũng có thể tính giá trị bitLine \ s mới trong mỗi đầu vào có thể!
Nand Nor và Xor đều đơn giản:
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]);
}
}
Đối với mỗi đầu vào có thể, nó đại diện cho cách BitLine mới sẽ hoạt động.
Xử lý bộ giải mã hơi khó một chút, nhưng ý tưởng là "nếu các bit ở đầu vào đại diện cho số x ở dạng nhị phân, thì dòng bit đầu ra x sẽ là đúng, trong khi tất cả các bit khác sẽ sai. Hàm này sẽ lấy một mảng bitline và thêm 8 bitline mới vào mảng.
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);
}
}
}
Bây giờ chúng ta có tất cả các yếu tố cơ bản của mình, vì vậy hãy nói về thuật toán:
Chúng tôi sẽ thực hiện một thuật toán đệ quy, ở mỗi độ sâu, nó sẽ cố gắng sử dụng các phần tử khác (cũng không phải là \ nand \ xor \ decoder) trên các bitline hiện có, và sau đó đặt phần tử thành không thể sử dụng cho độ sâu đệ quy tiếp theo. Bất cứ khi nào chúng tôi đến cuối cùng và chúng tôi không có nhiều yếu tố để sử dụng, chúng tôi sẽ kiểm tra xem chúng tôi có một bitline đó là những gì chúng tôi đang tìm kiếm.
Mã này kiểm tra trong bất kỳ thời điểm nào cho dù nhóm dòng hiện tại có chứa dòng chúng tôi đang tìm kiếm hay không:
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;
}
Đây là chức năng mà nó sử dụng để kiểm tra xem hai dòng có bằng nhau không:
bool CheckEquals(BitLine other)
{
for (var i = 0; i < 16; i++)
{
if (this.IsActiveWhenInputIs[i] != other.IsActiveWhenInputIs[i])
{
return false;
}
}
return true;
}
Ok, vậy bây giờ đối với phần chính, đây là thuật toán chính:
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;
}
}
Hàm này nhận được danh sách các bitLines có sẵn, độ dài danh sách, boolean đại diện cho dù mỗi phần tử hiện có sẵn (xor / nor / nand / decoder) và bitLine đại diện cho bitLine mà chúng ta đang tìm kiếm.
Ở mỗi giai đoạn, nó sẽ kiểm tra xem chúng ta có sử dụng thêm phần tử nào không, nếu không - nó sẽ kiểm tra xem chúng ta có lưu trữ bitline cần thiết hay không.
Nếu chúng ta vẫn có nhiều phần tử hơn, thì đối với mỗi phần tử, nó gọi một hàm có nhiệm vụ xử lý việc tạo bitLines mới bằng cách sử dụng các phần tử đó và gọi độ sâu hồi quy tiếp theo sau đó.
Các hàm xử lý tiếp theo đều khá đơn giản, chúng có thể được dịch thành "chọn 2 \ 3 từ các bitline có sẵn và kết hợp chúng bằng cách sử dụng phần tử có liên quan. Sau đó, gọi độ sâu tiếp theo của đệ quy, chỉ là lần này nó sẽ không chứa yếu tố này! ".
đó là các chức năng:
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;
}
Và đây là nó, chúng ta chỉ cần gọi hàm này với dòng cần thiết mà chúng ta đang tìm kiếm và nó kiểm tra mọi sự kết hợp có thể có của các bộ phận điện để kiểm tra xem có thể kết hợp chúng theo cách mà cuối cùng một dòng sẽ xuất ra với các giá trị cần thiết.
* lưu ý rằng tôi luôn sử dụng cùng một danh sách, vì vậy tôi sẽ không cần phải tạo các phiên bản bitline mới mọi lúc. Tôi cho nó một bộ đệm 200 vì lý do đó.
Đây là chương trình hoàn chỉnh:
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();
}
}
}
Hy vọng lần này là một lời giải thích hợp lệ: P