//         
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 Const nStone=20;
       nOsobi=50;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  Data=Record
     Mesto:String[nStone];
     r:integer;
  End;

var
  Form1: TForm1;
  m:array[1..nStone] of integer;
  Osobi:array[1..2*nOsobi] of Data;
  Min:integer;

implementation

{$R *.dfm}
//   
Procedure Generation(Var p:boolean;Var OptOsobi:Data);
Var i,j,m1,m2,k:integer;
begin
    For i:=1 to nStone do begin
      m[i]:=Random(100);
      form1.memo2.Lines.Add(intToStr(m[i]));
    end;

    For i:=1 to nOsobi do begin
       m1:=0;m2:=0;
       Osobi[i].Mesto:='';
       For j:=1 to nStone do begin
          k:=Random(2);
          Osobi[i].Mesto:=Osobi[i].Mesto+IntToStr(k);
          If k=0 then m1:=m2+m[j]
                 else m2:=m2+m[j]
       end;
       Osobi[i].r:=Abs(m1-m2);
       If Abs(m1-m2)<Min then begin
           Min:=Abs(m1-m2);
           OptOsobi:=Osobi[i]
       end;

       If Abs(m1-m2)=0 then begin
             OptOsobi:=Osobi[i];
             p:=True;
             Exit
       end
    end;
end;

// 
Procedure Crossing(Var p:boolean;Var OptOsobi:Data);
Var i,j,k,m1,m2:integer;
    s1,s2,s3,s4:string;

begin
    For i:=1 to nOsobi Div 2 do begin
        k:=1+Random(nStone-1);
        s1:=Copy(Osobi[i].Mesto,1,k);
        s2:=Copy(Osobi[i].Mesto,k+1,nStone-k);

        s3:=Copy(Osobi[i+nOsobi Div 2].Mesto,1,k);
        s4:=Copy(Osobi[i+nOsobi Div 2].Mesto,k+1,nStone-k);

        Osobi[2*i+nOsobi-1].Mesto:=s1+s4;
        Osobi[2*i+nOsobi].Mesto:=s3+s2;
    end;

    For i:=nOsobi+1 to 2*nOsobi do begin
         m1:=0;m2:=0;
         For j:=1 to nStone do
             If Osobi[i].Mesto[j]='0' then m1:=m1+m[j]
                                      else m2:=m2+m[j];
         Osobi[i].r:=Abs(m1-m2);

         If Abs(m1-m2)<Min then begin
           Min:=Abs(m1-m2);
           OptOsobi:=Osobi[i]
         end;
         If Abs(m1-m2)=0 then begin
             OptOsobi:=Osobi[i];
             p:=True;
             Exit
         end
    end;
end;

//  
Procedure Mutation(Var p:boolean;Var OptOsobi:Data);
Var j,k,k1,m1,m2:integer;
    q:real;
begin
    q:=Random;
    If q>0.05 then Exit;

    k:=1+Random(2*nOsobi-1);
    k1:=1+Random(nStone);
    If Osobi[k].Mesto[k1]='0' then Osobi[k].Mesto[k1]:='1'
                              else Osobi[k].Mesto[k1]:='0';

    m1:=0;m2:=0;
    For j:=1 to nStone do
        If Osobi[k].Mesto[j]='0' then m1:=m1+m[j]
                                 else m2:=m2+m[j];
    Osobi[k].r:=Abs(m1-m2);

    If Abs(m1-m2)<Min then begin
        Min:=Abs(m1-m2);
        OptOsobi:=Osobi[k]
    end;

    If Abs(m1-m2)=0 then begin
        OptOsobi:=Osobi[k];
        p:=True;
        Exit
    end
end;


procedure TForm1.Button1Click(Sender: TObject);
Var i:integer;
    OptOsobi:Data;
    p:boolean;
begin
    //   
    Min:=MaxInt;
    Generation(p,OptOsobi);

    //  
    
    If Not p then
    For i:=1 to 500 do begin
        Crossing(p,OptOsobi);
        If p then Break;
        Mutation(p,OptOsobi);
        If p then Break;
    end;

    Memo1.Lines[0]:=OptOsobi.Mesto+' r='+IntToStr(OptOsobi.r)+' ';
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Close
end;

end.
