Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit Get24Unit;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls, Generics.Collections;
- type
- TForm1 = class(TForm)
- Memo1: TMemo;
- Button1: TButton;
- Edit1: TEdit;
- procedure Button1Click(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- end;
- type
- TReversePolishNotation = class (TObject)
- private
- FNotation: string;
- //стек для генерации ответа
- FSolveStack: TStack<string>;
- //стек для генерации инфиксной нотации
- FInfixStack: TStack<string>;
- public
- InfixNotation: string;
- constructor Create(aNotation: string);
- destructor Destroy; override;
- function Solve: string;
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- { TReversePolishNotation}
- constructor TReversePolishNotation.Create(aNotation: string);
- begin
- inherited Create;
- self.FNotation:=aNotation;
- self.FSolveStack:=TStack<string>.Create;
- self.FInfixStack:=TStack<string>.Create;
- end;
- destructor TReversePolishNotation.Destroy;
- begin
- self.FSolveStack.Free;
- self.FInfixStack.Free;
- inherited Destroy;
- end;
- function TReversePolishNotation.Solve: string;
- var
- i,j: integer;
- Token: string;
- arg1,arg2: extended;
- arg1infix,arg2infix: string;
- tmp: extended;
- begin
- try
- i:=0;
- repeat
- //идём по польской нотации, пока не натыкаемся на пробел
- j:=i+1;
- repeat
- Inc(i)
- until self.FNotation[i]=' ';
- //копируем в Token часть до пробела (оператор или аргумент)
- Token:=copy(self.FNotation,j,i-j);
- //если это не оператор - кладём в стек
- if not CharInSet(Token[1],['+','-','*','/']) then begin
- FSolveStack.Push(Token);
- FInfixStack.Push(Token);
- end
- //иначе - оператор
- else begin
- //достаём аргументы в обратном порядке
- arg2:=strtofloat(self.FSolveStack.Pop);
- arg1:=strtofloat(self.FSolveStack.Pop);
- //применяем оператор и кладём результат в стек
- case Token[1] of
- '+': self.FSolveStack.Push(floattostr(arg1+arg2));
- '-': self.FSolveStack.Push(floattostr(arg1-arg2));
- '*': self.FSolveStack.Push(floattostr(arg1*arg2));
- '/': self.FSolveStack.Push(floattostr(arg1/arg2));
- end;
- //делаем тоже самое, но без вычисления, для сборки в инфиксную нотацию
- arg2infix:=FInfixStack.Pop;
- arg1infix:=FInfixStack.Pop;
- if not TryStrToFloat(arg2infix,tmp) then
- arg2infix:='('+arg2infix+')';
- if not TryStrToFloat(arg1infix,tmp) then
- arg1infix:='('+arg1infix+')';
- FInfixStack.Push(
- arg1infix+Token+arg2infix
- );
- end;
- //цикл выполняется до тех пор пока не пройдём по всей польской нотации
- until (i>=Length(self.FNotation));
- //ответ лежит в стеке
- Result:=self.FSolveStack.Pop;
- self.InfixNotation:=self.FInfixStack.Pop;
- except
- Result:='Error';
- end;
- end;
- { TForm1 }
- procedure TForm1.Button1Click(Sender: TObject);
- var
- Solver: TReversePolishNotation;
- Answer: string;
- Numbers: TList<integer>;
- Operators: TList<char>;
- buf: string;
- i: integer;
- NumberIndex: integer;
- begin
- Operators:=TList<char>.Create;
- Operators.AddRange(['+','-','*','/']);
- Answer:='';
- while Answer<>'24' do begin
- Numbers:=TList<integer>.Create;
- Numbers.AddRange([1,3,4,6]);
- buf:='';
- //составляем ОПН из 4х чисел и 3х операторов
- for i:=0 to 3 do begin
- NumberIndex:=random(Numbers.Count);
- buf:=buf+inttostr(Numbers[NumberIndex])+' ';
- Numbers.Delete(NumberIndex);
- end;
- for i:=0 to 2 do
- buf:=buf+Operators[random(Operators.Count)]+' ';
- Solver:=TReversePolishNotation.Create(buf);
- try
- Answer:=Solver.Solve;
- if Answer='24' then
- memo1.Lines.Add(Solver.InfixNotation+'=24');
- finally
- Solver.Free;
- end;
- Numbers.Free;
- end;
- Operators.Free;
- end;
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- Randomize;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement