program hradla; {$APPTYPE CONSOLE} uses SysUtils, Classes, Contnrs, IniFiles, Dialogs, DateUtils; type TGateType = (nnot, nand, nor, nxor, nnet); TData = array[0..100] of Integer; TDynData = array of Integer; TNet = class Stav: TData; Gates: TObjectList; InCount: Integer; OutCount: Integer; Outputs: TData; Pamet: Integer; constructor Create; procedure ProcessNet(Inp: TDynData; Outp: TDynData); end; TGate = class GateType: TGateType; Parent: TNet; InCount: Integer; OutCount: Integer; Inputs: TData; Outputs: TData; ForNet: TNet; constructor Create; procedure ProcessGate; end; 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: TDynData; begin HasAll := true; for i := 0 to InCount-1 do if Parent.Stav[Inputs[i]] = 2 then begin HasAll := false; Break; end; if HasAll then case GateType of 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 SetLength(CIns, InCount); SetLength(COuts, OutCount); for i := 0 to InCount-1 do CIns[i] := Parent.Stav[Inputs[i]]; ForNet.ProcessNet(CIns, COuts); for i := 0 to OutCount-1 do Parent.Stav[Outputs[i]] := COuts[i]; end; end; end; procedure TNet.ProcessNet(Inp: TDynData; Outp: TDynData); function Finished: Boolean; var i: Integer; 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; while not Finished do begin 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; begin P := Pos(Name+'=', S)+Length(Name)+2; //WriteLn(P); Result := EmptyStr; while S[P] <> '''' do begin Result := Result + S[P]; Inc(P); end; end; function GetTag(S: String): String; var P: Integer; 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 SetLength(Data, Length(Data)+1); Data[High(Data)] := V; end;*) procedure LoadNet(Net: TNet; FileName: String); var Vstup: TStringList; Aliasy: THashedStringList; i, Faze, Misto: Integer; PomGate: TGate; S, Hodnota, Tag: String; begin Vstup := TStringList.Create; Vstup.LoadFromFile(FileName); Aliasy := THashedStringList.Create; //Net := TNet.Create; Faze := 1; for i := 1 to Vstup.Count-1 do begin S := Trim(Vstup[i]); Tag := GetTag(S); //WriteLn(i, ' ', Faze, ' ', Tag); if Faze = 1 then begin if (Tag = 'input') then begin Aliasy.Add(GetValue(S, 'id')); //WriteLn('OK'); Inc(Net.InCount); end else Faze := 2; end; if Faze = 2 then begin 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; PomGate.ForNet := TNet.Create; LoadNet(PomGate.ForNet, Hodnota); end; PomGate.Parent := Net; Faze := 3; end else if (Tag = 'output') or (Tag = 'input') then Faze := 4; end; if Faze = 3 then begin if Tag = 'input' then begin Hodnota := GetValue(S, 'id'); Misto := Aliasy.IndexOf(Hodnota); if Misto = -1 then begin Aliasy.Add(Hodnota); Misto := Aliasy.Count-1; end; //AddData(PomGate.Inputs, Misto); PomGate.Inputs[PomGate.InCount] := Misto; Inc(PomGate.InCount); end else if Tag = 'output' then begin Hodnota := GetValue(S, 'id'); Misto := Aliasy.IndexOf(Hodnota); if Misto = -1 then begin Aliasy.Add(Hodnota); Misto := Aliasy.Count-1; end; //AddData(PomGate.Outputs, Misto); PomGate.Outputs[PomGate.OutCount] := Misto; Inc(PomGate.OutCount); end else if Tag = '/gate' then Faze := 2; end; if Faze = 4 then begin if Tag = 'output' then begin Hodnota := GetValue(S, 'id'); Misto := Aliasy.IndexOf(Hodnota); //AddData(Net.Outputs, Misto); Net.Outputs[Net.OutCount] := Misto; Inc(Net.OutCount); end else if Tag = '/net' then begin Net.Pamet := Aliasy.Count; //SetLength(Net.Stav, Net.Pamet); Break; end; end; end; Vstup.Free; Aliasy.Free; end; procedure StrToInput(S: String; Inp: TDynData); 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: TDynData): 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: TDynData; 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...'); Z := Now; LoadNet(MainNet, OP.FileName); WriteLn(MillisecondsBetween(Now, Z); ReadLn; SetLength(GInput, MainNet.InCount); SetLength(GOutput, MainNet.OutCount); AssignFile(F, OP.FileName + '.in'); Reset(F); //i := 0; WriteLn; WriteLn('vystup:'); while not EoF(F) do begin //Inc(i); //WriteLn(i); ReadLn(F, S); StrToInput(S, GInput); MainNet.ProcessNet(GInput, GOutput); WriteLn(OutputToStr(GOutput)); end; WriteLn('stiskem klavesy enter ukoncite program'); ReadLn; end; end.