using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.IO; namespace vyhodnoceni { public class Network { private static Dictionary networks = new Dictionary { }; // vytvori sit nebo vrati drive vytvorenou public static Network GetNetwork(string netFile) { if (!networks.ContainsKey(netFile)) { networks[netFile] = new Network(netFile); } return networks[netFile]; } // hlavni vstupy se chovaji stejne jako vystupy uvnitr hradel (a naopak) private List globalInputs = new List { }; private List globalOutputs = new List { }; private List gates = new List { }; // seznamy vsech vstupu a vystupu private List inputs = new List { }; private Dictionary outputs = new Dictionary { }; // pro testovani public bool Testing { get; set; } public string OutputData { get; private set; } // zpracuje xml soubor a vytvori strukturu objektu private Network(string netFile) { Testing = false; var xml = new XmlDocument(); xml.Load(netFile); foreach (XmlElement item in xml.ChildNodes[0].ChildNodes) { switch (item.Name) { case "input": globalInputs.Add(CreateOutput(item)); break; case "output": globalOutputs.Add(CreateInput(item)); break; case "gate": gates.Add(CreateGate(item)); break; default: throw new NotSupportedException("Tag " + item.Name + " neni podporovany."); } } // spoji vstupy s prislusnimy vystupy foreach (var input in inputs) { string id = input.GetId(); if (!outputs.ContainsKey(id)) throw new Exception("Neexistuje vystupni prvek s id = '" + id + "'"); input.SetOutput(outputs[id]); } } // zpracuje vstupni soubor public void ProcessFile(string inputFile) { var reader = new StreamReader(inputFile); while (!reader.EndOfStream) { string inputLine = reader.ReadLine().Trim(); string outputLine = ProcessLine(inputLine); if (outputLine != null) { if (!Testing) { Console.WriteLine(outputLine); } else { OutputData += outputLine + "\r\n"; } } else { Console.WriteLine(""); } } reader.Close(); } // zpracuje radek vstupniho souboru private string ProcessLine(string inputLine) { if (inputLine.Length != globalInputs.Count) return null; var data = new bool[globalInputs.Count]; for (int i = 0; i < globalInputs.Count; i++) { data[i] = CharToBool(inputLine[i]); } var outputData = ProcessData(data); var outputLine = new StringBuilder(globalOutputs.Count); foreach (var item in outputData) { outputLine.Append(BoolToChar(item)); } return outputLine.ToString(); } // zpracuje vstupni data public bool[] ProcessData(bool[] data) { ResetNetwork(); // nastavi pocatecni hodnoty for (int i = 0; i < globalInputs.Count; i++) { globalInputs[i].SetValue(data[i]); } bool done = false; while (!done) { // spocita hodnoty hradel, pokud je to mozne bool changed = false; foreach (var gate in gates) { if (!gate.HasValue()) { changed |= gate.Calculate(); } } if (!changed) { // nic se nezmenilo, vypocet je tedy snad hotovy done = true; foreach (var output in globalOutputs) { done &= output.HasValue(); if (!done) break; } if (!done) { // vypocet neni hotovy throw new Exception("Spatna sit, nejde vyresit"); } } } // posbira vystupni data var outputData = new bool[globalOutputs.Count]; for (int i = 0; i < globalOutputs.Count; i++) { outputData[i] = globalOutputs[i].GetValue(); } return outputData; } // pripravi sit pro dalsi vypocet private void ResetNetwork() { foreach (var item in gates) { item.Reset(); } foreach (var item in outputs) { item.Value.Reset(); } } private char BoolToChar(bool value) { return value ? '1' : '0'; } private bool CharToBool(char ch) { switch (ch) { case '0': return false; case '1': return true; default: throw new NotSupportedException("Znak '" + ch + "' ve vstupnich datech neni podporovan."); } } private Input CreateInput(XmlElement item) { string id = item.Attributes["id"].Value; var input = new Input(id); inputs.Add(input); return input; } private Output CreateOutput(XmlElement item) { string id = item.Attributes["id"].Value; var output = new Output(id); outputs.Add(id, output); return output; } private Gate CreateGate(XmlElement item) { string type = item.Attributes["type"].Value; type = type.ToLower(); // vytvori branu Gate gate = null; switch (type) { case "and": gate = new AndGate(); break; case "or": gate = new OrGate(); break; case "xor": gate = new XorGate(); break; case "not": gate = new NotGate(); break; default: gate = new ComplexGate(type); break; } // prida brane vstupy a vystupy foreach (XmlElement child in item) { switch (child.Name) { case "input": gate.Add(CreateInput(child)); break; case "output": gate.Add(CreateOutput(child)); break; default: throw new NotSupportedException("Tag " + child.Name + " neni podporovany."); } } return gate; } } }