program hradla; {$APPTYPE CONSOLE} uses SysUtils, Classes, Contnrs, IniFiles, Dialogs, DateUtils; type TGateType = (nnot, nand, nor, nxor, nnet); // mozne typy hradel TData = array of Cardinal; TNet = class // objekt uchovavajici sit Stav: TData; // aktualni stav site - jaka je informace na jednotlivych dratech Gates: TObjectList; // objekt uchovavajici vsechna hradla site hradla InCount: Integer; // pocet vstupu site OutCount: Integer; // pocet vystupu site Outputs: TData; // seznam vystupu Pamet: Integer; // velikost Stavu constructor Create; procedure ProcessNet(Inp: TData; Outp: TData); // procedura zpracovavajici vstup end; TGate = class // objekt hradla GateType: TGateType; // typ hradla Parent: TNet; // sit ve ktere hradlo je InCount: Integer; // pocet vstupu hradla OutCount: Integer; // pocet vystupu hradla Inputs: TData; // vstupy hradla - hodnoty odpovidaji indexum Stavu site Outputs: TData; // vystupy - totez ForNet: TNet; // sit, kterou hradlo reprezentuje (pokud je typu sit) constructor Create; procedure ProcessGate; // procedura zpracovavajici vstup (pokud neni kompletni end; // tak nic neudela) constructor TNet.Create; begin inherited Create; Gates := TObjectList.Create; InCount := 0; OutCount := 0; SetLength(Outputs, 0); end; constructor TGate.Create; begin inherited Create; InCount := 0; OutCount := 0; SetLength(Inputs, 0); SetLength(Outputs, 0); end; procedure TGate.ProcessGate; var i, Sum: Integer; HasAll: Boolean; CIns, COuts: TData; begin HasAll := true; for i := 0 to InCount-1 do if Parent.Stav[Inputs[i]] = 2 then begin HasAll := false; // test jestli uz hradlo zna vsechny sve vstupy Break; end; if HasAll then case GateType of // dale se rozhoduje podle typu hradla nnot: Parent.Stav[Outputs[0]] := 1 - Parent.Stav[Inputs[0]]; nor: begin Parent.Stav[Outputs[0]] := 0; for i := 0 to InCount-1 do if Parent.Stav[Inputs[i]] = 1 then begin Parent.Stav[Outputs[0]] := 1; Break; end; end; nand: begin Parent.Stav[Outputs[0]] := 1; for i := 0 to InCount-1 do if Parent.Stav[Inputs[i]] = 0 then begin Parent.Stav[Outputs[0]] := 0; Break; end; end; nxor: begin Sum := 0; for i := 0 to InCount-1 do Sum := Sum xor Parent.Stav[Inputs[i]]; Parent.Stav[Outputs[0]] := Sum; end; nnet: begin // pokud hradlo reprezentuje dalsi sit SetLength(CIns, InCount); // tak se vytvori pole pro vstup a vystup SetLength(COuts, OutCount); for i := 0 to InCount-1 do CIns[i] := Parent.Stav[Inputs[i]]; ForNet.ProcessNet(CIns, COuts); // dana sit zpracuje vstup a ulozi do vystupu for i := 0 to OutCount-1 do Parent.Stav[Outputs[i]] := COuts[i]; end; end; end; procedure TNet.ProcessNet(Inp: TData; Outp: TData); function Finished: Boolean; // funkce rozhodujici jestli uz je sit cela spoctena var i: Integer; // to je tehdy pokud jsou zname vsechny vystupy begin Result := true; for i := 0 to OutCount-1 do if Stav[Outputs[i]] = 2 then begin Result := false; Break; end; end; var i: Integer; begin for i := 0 to Pamet-1 do if i < InCount then Stav[i] := Inp[i] else Stav[i] := 2; // dvojka odpovida neznamemu stavu dratu while not Finished do begin // cykli se dokud nejsou zname vsechny vystupy for i := 0 to Gates.Count-1 do (Gates[i] as TGate).ProcessGate; end; for i := 0 to OutCount-1 do Outp[i] := Stav[Outputs[i]]; end; function GetValue(S, Name: String): String; var P: Integer; // funkce nacitajici hodnotu nejakeho parametru tagu begin P := Pos(Name+'=', S)+Length(Name)+2; Result := EmptyStr; while S[P] <> '''' do begin Result := Result + S[P]; Inc(P); end; end; function GetTag(S: String): String; var P: Integer; // funkce nacitajici jmeno tagu begin P := 2; Result := EmptyStr; while not (S[P] in [' ', '>']) do begin Result := Result + S[P]; Inc(P); end; Result := LowerCase(Result); end; procedure AddData(var Data: TData; V: Integer); begin // procedura pridavajici prvek do dyn. pole celych cisel SetLength(Data, Length(Data)+1); Data[High(Data)] := V; end; procedure LoadNet(Net: TNet; FileName: String); // procedura nacteni site var Vstup: TStringList; // soubor s popisem hradel Aliasy: THashedStringList; // objekt prirazujici cisla jednotlivym dratum (misto jmen) i, Faze, Misto: Integer; PomGate: TGate; S, Hodnota, Tag: String; begin Vstup := TStringList.Create; Vstup.LoadFromFile(FileName); // nacte se soubor... Aliasy := THashedStringList.Create; Faze := 1; for i := 1 to Vstup.Count-1 do begin S := Trim(Vstup[i]); //orezani od odsazeni ap. Tag := GetTag(S); // zjisti se aktualni tag if Faze = 1 then begin // Faze 1 - nacitaji se vstupy site if (Tag = 'input') then begin Aliasy.Add(GetValue(S, 'id')); Inc(Net.InCount); end else Faze := 2; // pokud uz nejsou inputy jde se na fazi 2 end; if Faze = 2 then begin // Faze 2 - nacitaji se hradla if Tag = 'gate' then begin PomGate := TGate.Create; Hodnota := GetValue(S, 'type'); Net.Gates.Add(PomGate); if Hodnota = 'and' then PomGate.GateType := nand else if Hodnota = 'or' then PomGate.GateType := nor else if Hodnota = 'xor' then PomGate.GateType := nxor else if Hodnota = 'not' then PomGate.GateType := nnot else begin PomGate.GateType := nnet; // pokud hradlo reprezentuje dalsi sit PomGate.ForNet := TNet.Create; // tak se tato sit vytvori LoadNet(PomGate.ForNet, Hodnota); // a nacte z prislusneho souboru end; PomGate.Parent := Net; // ulozi se sit do ktere hradlo patri Faze := 3; // a jde se na fazi 3 - nacitani vstupu a vystupu hradel end else if (Tag = 'output') or (Tag = 'input') then Faze := 4; end; // pokud misto hradla nachazime neco jineho, znamena to, ze se jdou nacitat // vystupy site - faze 4 if Faze = 3 then begin // Faze 3 - nacitaji se vstupy a vystupy hradel if Tag = 'input' then begin Hodnota := GetValue(S, 'id'); Inc(PomGate.InCount); Misto := Aliasy.IndexOf(Hodnota); // hledani, jestli uz dany drat neni ocislovan if Misto = -1 then begin // pokud neni, prida se mu cislo Aliasy.Add(Hodnota); Misto := Aliasy.Count-1; end; AddData(PomGate.Inputs, Misto); // cislo vstupu se ulozi mezi vstupy hradla end else if Tag = 'output' then begin Hodnota := GetValue(S, 'id'); Inc(PomGate.OutCount); Misto := Aliasy.IndexOf(Hodnota); // vystupy - analogicke ke vstupum if Misto = -1 then begin Aliasy.Add(Hodnota); Misto := Aliasy.Count-1; end; AddData(PomGate.Outputs, Misto); end else if Tag = '/gate' then Faze := 2; // pokud konci hradlo, jde se hledat dalsi end; if Faze = 4 then begin // Faze 4 - nacitaji se vystupy site if Tag = 'output' then begin Hodnota := GetValue(S, 'id'); Misto := Aliasy.IndexOf(Hodnota); // uz nemusime testovat, jestli jsou tyto vystupy AddData(Net.Outputs, Misto); // ocislovane, protoze uz urcite byly u nejakych Inc(Net.OutCount); // hradel end else if Tag = '/net' then begin Net.Pamet := Aliasy.Count; // pokud konci sit, ulozime pocet vsech dratu SetLength(Net.Stav, Net.Pamet); // (Pamet) Break; end; end; end; Vstup.Free; Aliasy.Free; end; procedure StrToInput(S: String; Inp: TData); var i: Integer; begin for i := 1 to Length(Inp) do if S[i] = '0' then Inp[i-1] := 0 else Inp[i-1] := 1; end; function OutputToStr(Outp: TData): String; var i: Integer; begin Result := EmptyStr; for i := 0 to High(Outp) do Result := Result + IntToStr(Outp[i]); end; var MainNet: TNet; //i, j: Integer; GInput, GOutput: TData; F: TextFile; OP: TOpenDialog; S: String; //Z: TDateTIme; begin MainNet := TNet.Create; OP := TOpenDialog.Create(nil); WriteLn('po stisku klavesy enter oznacte soubor s popisem hradlove site'); ReadLn; if OP.Execute and FileExists(OP.FileName) then begin WriteLn('zpracovavam soubor s hradly, muze to chvili trvat...'); LoadNet(MainNet, OP.FileName); // nacte se cela sit SetLength(GInput, MainNet.InCount); SetLength(GOutput, MainNet.OutCount); AssignFile(F, OP.FileName + '.in'); // nacteni souboru se vstupy - stejne jmeno Reset(F); // jen se prida pripona //i := 0; WriteLn; WriteLn('vystup:'); while not EoF(F) do begin //Inc(i); //WriteLn(i); ReadLn(F, S); // postupne se nacitaji a zpracovavaji vstupy S := Trim(S); StrToInput(S, GInput); MainNet.ProcessNet(GInput, GOutput); WriteLn(OutputToStr(GOutput)); end; WriteLn('stiskem klavesy enter ukoncite program'); ReadLn; end; end.