Guest User

# Get24 for hashcode.ru @ vk.com/zhukovsd

a guest
Jul 20th, 2012
193
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. unit Get24Unit;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls, Generics.Collections;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Memo1: TMemo;
  12.     Button1: TButton;
  13.     Edit1: TEdit;
  14.     procedure Button1Click(Sender: TObject);
  15.     procedure FormCreate(Sender: TObject);
  16.   end;
  17.  
  18. type
  19.   TReversePolishNotation = class (TObject)
  20.   private
  21.     FNotation: string;
  22.  
  23.     //стек для генерации ответа
  24.     FSolveStack: TStack<string>;
  25.     //стек для генерации инфиксной нотации
  26.     FInfixStack: TStack<string>;
  27.   public
  28.     InfixNotation: string;
  29.  
  30.     constructor Create(aNotation: string);
  31.     destructor Destroy; override;
  32.  
  33.     function Solve: string;
  34.   end;
  35.  
  36. var
  37.   Form1: TForm1;
  38.  
  39. implementation
  40.  
  41. {$R *.dfm}
  42.  
  43. { TReversePolishNotation}
  44.  
  45. constructor TReversePolishNotation.Create(aNotation: string);
  46. begin
  47.   inherited Create;
  48.  
  49.   self.FNotation:=aNotation;
  50.   self.FSolveStack:=TStack<string>.Create;
  51.   self.FInfixStack:=TStack<string>.Create;
  52. end;
  53.  
  54. destructor TReversePolishNotation.Destroy;
  55. begin
  56.   self.FSolveStack.Free;
  57.   self.FInfixStack.Free;
  58.  
  59.   inherited Destroy;
  60. end;
  61.  
  62. function TReversePolishNotation.Solve: string;
  63. var
  64.   i,j: integer;
  65.   Token: string;
  66.  
  67.   arg1,arg2: extended;
  68.   arg1infix,arg2infix: string;
  69.  
  70.   tmp: extended;
  71. begin
  72.   try
  73.     i:=0;
  74.  
  75.     repeat
  76.       //идём по польской нотации, пока не натыкаемся на пробел
  77.       j:=i+1;
  78.       repeat
  79.         Inc(i)
  80.       until self.FNotation[i]=' ';
  81.  
  82.       //копируем в Token часть до пробела (оператор или аргумент)
  83.       Token:=copy(self.FNotation,j,i-j);
  84.  
  85.       //если это не оператор - кладём в стек
  86.       if not CharInSet(Token[1],['+','-','*','/']) then begin
  87.         FSolveStack.Push(Token);
  88.         FInfixStack.Push(Token);
  89.       end
  90.       //иначе - оператор
  91.       else begin
  92.         //достаём аргументы в обратном порядке
  93.         arg2:=strtofloat(self.FSolveStack.Pop);
  94.         arg1:=strtofloat(self.FSolveStack.Pop);
  95.  
  96.         //применяем оператор и кладём результат в стек
  97.         case Token[1] of
  98.           '+': self.FSolveStack.Push(floattostr(arg1+arg2));
  99.           '-': self.FSolveStack.Push(floattostr(arg1-arg2));
  100.           '*': self.FSolveStack.Push(floattostr(arg1*arg2));
  101.           '/': self.FSolveStack.Push(floattostr(arg1/arg2));
  102.         end;
  103.  
  104.         //делаем тоже самое, но без вычисления, для сборки в инфиксную нотацию
  105.         arg2infix:=FInfixStack.Pop;
  106.         arg1infix:=FInfixStack.Pop;
  107.  
  108.         if not TryStrToFloat(arg2infix,tmp) then
  109.           arg2infix:='('+arg2infix+')';
  110.  
  111.         if not TryStrToFloat(arg1infix,tmp) then
  112.           arg1infix:='('+arg1infix+')';
  113.  
  114.         FInfixStack.Push(
  115.           arg1infix+Token+arg2infix
  116.         );
  117.       end;
  118.     //цикл выполняется до тех пор пока не пройдём по всей польской нотации
  119.     until (i>=Length(self.FNotation));
  120.  
  121.     //ответ лежит в стеке
  122.     Result:=self.FSolveStack.Pop;
  123.  
  124.     self.InfixNotation:=self.FInfixStack.Pop;
  125.   except
  126.     Result:='Error';
  127.   end;
  128. end;
  129.  
  130. { TForm1 }
  131.  
  132. procedure TForm1.Button1Click(Sender: TObject);
  133. var
  134.   Solver: TReversePolishNotation;
  135.   Answer: string;
  136.  
  137.   Numbers: TList<integer>;
  138.   Operators: TList<char>;
  139.   buf: string;
  140.  
  141.   i: integer;
  142.   NumberIndex: integer;
  143. begin
  144.   Operators:=TList<char>.Create;
  145.   Operators.AddRange(['+','-','*','/']);
  146.  
  147.   Answer:='';
  148.   while Answer<>'24' do begin
  149.     Numbers:=TList<integer>.Create;
  150.     Numbers.AddRange([1,3,4,6]);
  151.  
  152.     buf:='';
  153.  
  154.     //составляем ОПН из 4х чисел и 3х операторов
  155.     for i:=0 to 3 do begin
  156.       NumberIndex:=random(Numbers.Count);
  157.       buf:=buf+inttostr(Numbers[NumberIndex])+' ';
  158.       Numbers.Delete(NumberIndex);
  159.     end;
  160.  
  161.     for i:=0 to 2 do
  162.       buf:=buf+Operators[random(Operators.Count)]+' ';
  163.  
  164.     Solver:=TReversePolishNotation.Create(buf);
  165.     try
  166.       Answer:=Solver.Solve;
  167.  
  168.       if Answer='24' then
  169.         memo1.Lines.Add(Solver.InfixNotation+'=24');
  170.     finally
  171.       Solver.Free;
  172.     end;
  173.  
  174.     Numbers.Free;
  175.   end;
  176.  
  177.   Operators.Free;
  178. end;
  179.  
  180. procedure TForm1.FormCreate(Sender: TObject);
  181. begin
  182.   Randomize;
  183. end;
  184.  
  185. end.
RAW Paste Data