Formulářové programování v Pascalu

Jenicek

Formulářové programování v Pascalu
« kdy: 06. 06. 2013, 17:06:52 »
Dobrý den,
jedná se o školní práci, kvůli které mám windows s Delphi a pořeboval bych, aby v proceduře NejblizsiBody došlo na konci k převodu proměnné typu real na string a dostat to do MemoPole. Nějak na to nemůžu přijít. Zjistil sem že programování asi nebude moje silná stránka a prosím o pomoc.

Kód: [Vybrat]
procedure NejblizsiBody (Mat: TMatice; n: Integer; var MemoBox: TMemo; var Xi,Xj,Yi,Yj,Min_find: Real);
var
  i,j: Integer;
  Vzdal: real;

begin
  Min_find:= maxint;
  for i := 1 to n-1 do begin
    for j := i+1 to n do begin
      Vzdal:= sqrt((sqr(mat[1,i]-mat[1,j]))+(sqr(mat[2,i]-mat[2,j])));
        if Vzdal < Min_find then begin
          Min_find:= Vzdal;

          Xi:=mat[1,i];
          Xj:=mat[1,j];
          Yi:=mat[2,i];
          Yj:=mat[2,j];
      end;
      floatTostr(Nejblizsibody(vzdal));
      MemoBox.Lines.Add ('Nejbližší body jsou:');
      MemoBox.Lines.Add (vzdal)
    end;
  end;
end;

Celý program:
- zadání:
Náhodným způsobem vygenerujte n dvojic reálných čísel v rozsahu A až B. Tyto dvojice považujte za kartézské souřadnice bodů v rovině. Nalezněte dva body s nejbližší vzdáleností a souřadnice obou bodů vytiskněte. Všechny dvojice a nejbližší dvojici vytiskněte do memo pole a do souboru.

Vstup: n – počet bodů – dvojic souřadnic, dolní a horní mez
Výstup: Souřadnice dvou bodů, které leží nejblíže.
Kód: [Vybrat]
unit Vzdalenost_Bodu;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const MAX = 100;

type
  Tmatice = array[1..MAX] of array [1..2] of integer;
  TForm1 = class(TForm)
    btnKonec: TButton;
    Button2: TButton;
    btnBudiz: TButton;
    edtB: TEdit;
    edtA: TEdit;
    edtN: TEdit;
    tmemo: TMemo;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    btnUlozit: TButton;
    procedure edtNEnter(Sender: TObject);
    procedure edtAEnter(Sender: TObject);
    procedure edtBEnter(Sender: TObject);
    procedure btnKonecClick(Sender: TObject);
    procedure btnBudizClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure btnUlozitClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  n,A,B,i,j:integer;
  X1,X2,Y1,Y2:real;
  Mat: TMatice;

implementation

{$R *.dfm}

procedure NahodMat (var Mat: TMatice; Min,Max: Integer);
var
  i,j: Integer;

begin
   Randomize;
   for i := 1 to 2 do
    for j := 1 to n do begin

      Mat [i,j]:= Min+Random (Max-Min+1);

  end;
end;


procedure MatDoTmem (var Mat: TMatice; MemoBox: TMemo; n: Integer);
var
  i,j: Integer;
  s: String;

begin
  for j := 1 to n do begin
  s:= '[' + IntToStr(j) + '] = ';
    for i := 1 to 2 do begin
    s:= s+ IntToStr (Mat [i,j]) + '  ';

    end;
      MemoBox.Lines.Add (s);
  end;
end;


procedure NejblizsiBody (Mat: TMatice; n: Integer; var MemoBox: TMemo; var Xi,Xj,Yi,Yj,Min_find: Real);
var
  i,j: Integer;
  Vzdal: real;

begin
  Min_find:= maxint;
  for i := 1 to n-1 do begin
    for j := i+1 to n do begin
      Vzdal:= sqrt((sqr(mat[1,i]-mat[1,j]))+(sqr(mat[2,i]-mat[2,j])));
        if Vzdal < Min_find then begin
          Min_find:= Vzdal;

          Xi:=mat[1,i];
          Xj:=mat[1,j];
          Yi:=mat[2,i];
          Yj:=mat[2,j];
      end;
      floatTostr(Nejblizsibody(vzdal));
      MemoBox.Lines.Add ('Nejbližší body jsou:');
      MemoBox.Lines.Add (vzdal)
    end;
  end;
end;

procedure TForm1.btnBudizClick(Sender: TObject);
var
Xi,Xj,Yi,Yj,Min_find:real;
begin
Tmemo.Text:= '';

  n:= StrToInt (edtN.Text);
  A:= StrToInt (edtA.Text);
  B:= StrToInt (edtB.Text);

  NahodMat (Mat, A, B);
  MatDoTmem (Mat, tmemo, n);
  NejblizsiBody (Mat,n,tmemo,Xi,Xj,Yi,Yj,Min_find);
end;

procedure TForm1.btnKonecClick(Sender: TObject);
begin
  close;
end;

procedure TForm1.btnUlozitClick(Sender: TObject);
var
  F: TextFile;
  i,j: Integer;

begin
  AssignFile (F, 'data.txt');
  ReWrite (F);

  for j := 1 to n do
    for i := 1 to 2 do
    WriteLn (F, '[' + IntToStr(j) + '] = ' + IntToStr(Mat[i,j]));

  CloseFile (F);
  ShowMessage ('Soubor data.txt byl vytvoren');

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  edtN.Text:= '';
  edtA.Text:= '';
  edtB.Text:= '';
  self.tmemo.Text:= '';
end;

procedure TForm1.edtAEnter(Sender: TObject);
begin
  self.edtA.Text:='';
end;

procedure TForm1.edtBEnter(Sender: TObject);
begin
  self.edtB.Text:='';
end;

procedure TForm1.edtNEnter(Sender: TObject);
begin
  self.edtN.Text:='';
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  Randomize;
  self.tmemo.Text:='';
end;
end.

Za jakoukoliv pomoc předem děkuji.
« Poslední změna: 06. 06. 2013, 17:12:00 od Petr Krčmář »


kuka

Re:Formulářové programování v Pascalu
« Odpověď #1 kdy: 06. 06. 2013, 17:27:59 »
O Delphi celkem nic nevim, takze bez podrobneho zkoumani ciste k logice jako takove:

Zapsani vzdalenosti by urcite melo byt az za cyklem, ktery ji hleda, nikoliv uvnitr.

Vysledna hodnota neni v promenne vzdal, ale min_find.

floatToStr je asi podle nazvu funkce, ktera pro float vstup vraci String, tzn. tak jak je zavolana to nema smysl, asi by to melo byt az v tom vypisu MemoBox.Lines.Add(floatTostr(min_find)).

Mas vypsat souradnice bodu, coz nikde nevidim - i po upravach viz vyse vypises pri trose stesti pouze vzdalenost. Souradnice si ale samozrejme muzes zapamatovat analogicky min_find a pak je vypsat.

Jenicek

Re:Formulářové programování v Pascalu (Vyřešeno)
« Odpověď #2 kdy: 06. 06. 2013, 18:27:54 »
Děkuji za radu stačilo to opravit jak jste říkal a trošku doladit s těmi body a už to běží. :) Takto ted vypadá kód:

Kód: [Vybrat]
procedure NejblizsiBody (Mat: TMatice; n: Integer; var MemoBox: TMemo; var Xi,Xj,Yi,Yj,Min_find: Real);
var
  i,j: Integer;
  Vzdal: real;

begin
  Min_find:= maxint;
  for i := 1 to n-1 do begin
    for j := i+1 to n do begin
      Vzdal:= sqrt((sqr(mat[1,i]-mat[1,j]))+(sqr(mat[2,i]-mat[2,j])));
        if Vzdal < Min_find then begin
          Min_find:= Vzdal;

          Xi:=mat[1,i];
          Xj:=mat[1,j];
          Yi:=mat[2,i];
          Yj:=mat[2,j];
      end;
    end;
  end;
  MemoBox.Lines.Add ('-----');
  MemoBox.Lines.Add ('Vzdálenost nejbližších bodů je:');
  MemoBox.Lines.Add(floatTostr(min_find));
  MemoBox.Lines.Add ('-----');
  MemoBox.Lines.Add ('Nejbližší body jsou:');
  MemoBox.Lines.Add('['+floatTostr(Xi)+','+floatTostr(Yi)+'] a ['+floatTostr(Xj)+','+floatTostr(Yj)+']');
  MemoBox.Lines.Add ('-----');
  end;

kei.101

Re:Formulářové programování v Pascalu
« Odpověď #3 kdy: 07. 06. 2013, 15:35:24 »
Ať žije "brute force" :D

死神

  • ***
  • 159
    • Zobrazit profil
Re:Formulářové programování v Pascalu
« Odpověď #4 kdy: 08. 06. 2013, 16:41:48 »
Jeníčku, slyšels někdy o tomhle http://en.wikipedia.org/wiki/R-tree? Nejenom programování zřejmě nebude tvoje silná stránka.


gamer

Re:Formulářové programování v Pascalu
« Odpověď #5 kdy: 09. 06. 2013, 09:48:08 »
Jeníčku, slyšels někdy o tomhle http://en.wikipedia.org/wiki/R-tree? Nejenom programování zřejmě nebude tvoje silná stránka.

Jaký smysl má trápit se s tím ve školním projektu? Jeho řešení odpovídá zadání a zcela ho splňuje. Mimochodem r-tree není zdaleka jediná metoda, jak to udělat:
http://en.wikipedia.org/wiki/Nearest_neighbor_search

Jeníček

Re:Formulářové programování v Pascalu
« Odpověď #6 kdy: 09. 06. 2013, 10:48:58 »
Nikdy jsem o tom neslyšel. :o Potřebuji pouze udělat zápočet + zkoušku z technické informatiky a dostudovat Strojního inženýra. ;) Nemyslím si, že se budu programováním někdy živit, ale je pravda že jsem se ho vždycky naučit. Na druhou stranu člověk nikdy neví. Ovšem momentálně na to mám "hrozně moc" času...  :(

死神

  • ***
  • 159
    • Zobrazit profil
Re:Formulářové programování v Pascalu
« Odpověď #7 kdy: 09. 06. 2013, 12:55:23 »
Jaký smysl má trápit se s tím ve školním projektu? Jeho řešení odpovídá zadání a zcela ho splňuje. Mimochodem r-tree není zdaleka jediná metoda, jak to udělat:
http://en.wikipedia.org/wiki/Nearest_neighbor_search

Jde o to, co vlastně člověk chce. Něco se naučit nebo to nějak spatlat, abych to měl za sebou. Tady jde zřejmě o ten druhý případ.

Re:Formulářové programování v Pascalu
« Odpověď #8 kdy: 09. 06. 2013, 13:50:19 »
@ Jaký smysl má trápit se s tím ve školním projektu? Jeho řešení odpovídá zadání a zcela ho splňuje.

Souhlas. Při pohledu na algoritmus mě ale napadá jedna snadná optimalizace. Protože mocnina a odmocnina jsou výpočetně náročnější, nejdřív bych si zkontroloval vzdálenost pouze x-ových souřadnic a y-ových souřadnic. Pokud jsou tyto větší než nejmenší nalezená vzdálenost (Min_Find), pak ani nemá smysl tu odmocninu počítat.

P_V

  • ***
  • 227
    • Zobrazit profil
    • E-mail
Re:Formulářové programování v Pascalu
« Odpověď #9 kdy: 09. 06. 2013, 14:29:28 »
Souhlas. Při pohledu na algoritmus mě ale napadá jedna snadná optimalizace. Protože mocnina a odmocnina jsou výpočetně náročnější, nejdřív bych si zkontroloval vzdálenost pouze x-ových souřadnic a y-ových souřadnic. Pokud jsou tyto větší než nejmenší nalezená vzdálenost (Min_Find), pak ani nemá smysl tu odmocninu počítat.
Ono by se to obešlo bez odmocniny úplně, když jde jen o porovnání, a výsledek ponechat jako int.

gamer

Re:Formulářové programování v Pascalu
« Odpověď #10 kdy: 09. 06. 2013, 14:30:19 »
Jde o to, co vlastně člověk chce. Něco se naučit nebo to nějak spatlat, abych to měl za sebou. Tady jde zřejmě o ten druhý případ.

Nemá smysl věnovat zbytečný čas školním projektům, protože když tam uděláš něco navíc, stejně to nikdo neocení. Lepší je využít volný čas na studium toho, co tě opravdu zajímá a čemu se chceš věnovat. Mimochodem když už doporučuješ použít k hledání nejbližších bodů nějaký super-hyperprostor-ideal-hashing-tree, bylo by také dobré zmínit, že konstrukce toho něco stojí, kód bude delší a méně přehledný a paměťová náročnost bude mnohem větší. A každý strom má oproti flat paměťové struktuře na reálném hardware jednu velkou chybu, téměř každý přístup k prvku znamená cache miss, který je hodně drahý, protože pamět je hrozně fragmentovaná. Nedá se říct, který algoritmus bude lepší, bez znalosti výchozích podmínek (kolik tam bude typicky prvků, jak často se budou ty prvky měnit a jak často je potřeba něco hledat, kolik na to mám paměti, na jakém hardware to vlasně poběží...). Znevažovat schopnosti Jeníčka jen kvůli algoritmu, který použil, je hloupé, on naopak po tom co dostal radu velmi rychle pochopil, kde má chybu a opravil to, takže hloupý nebude.