IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Test possibilités possible longue boucle


Sujet :

Delphi

  1. #41
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Je viens de ré-allumer mon micro pour ajouter un détail dans mom dernier message quand j'ai vu que la discussion a avancé depuis.

    A e-ric : Merci pour la rectifification de mon bug : je testerai demain.

    Tu dis à ShailLeTroll :
    J'ai cru comprendre (et je ne suis pas le seul) que c'était les combinaisons qui étaient recherchées pas les arrangements.
    Vaut mieux se baser sur la 2ème Citation qui figure dans le message de BATiViR du 21/05/2007, 11h46 pour piger ce qu'il veut c'est clair et sans ambigüité. Car le mot "combinaison" est souvent utilisé dans le sens global du langage courant. Par contre dans le langage matheux on fait une distiction entre "permutations", "arrangements", "combinaisons" et pire encore car lorsque n = p un arrangement ne s'appelle plus arrangement mais permutation.

    De plus à partir du moment (msg 21/05/2007 17h48) où BATiViR t'a dit "parfait exactement ce que je cherchais, j'ai réussi a raccourcir ta fonction" j'ai considéré pour ma part que l'aspect purement mathématique était achevé.
    Et le code qu'il a lui même raccourci il génère un nombre de combinaisons-du-language-de-la-rue égale à NbCar^NbCar (c'est kif-kif au "n puissance k" quand k = n) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    - pour [/B]3 caractères      27 combinaisons-langue-de-la-rue,
    - pour 4 caractères    256 combinaisons,
    - pour 5 caractères  3125 combinaisons,
    - pour 6 caractères 46656 combinaisons,
    Le pb des maths étant résolu, restait donc plus qu'à optimiser le code sous l'angle de la rapidité par exemple.

    Par contre j'avais cru comprendre que les 6 secondes citées en gras dans le message d'aujourdui 11h59 de ShaiLeTroll correspondait au cas "abcdef" soit 46656 combinaisons-arrangements et dans celui de 18h03 je lis "22 000 ms pour 39 000 000". Une règle de trois pour se faire une idée donnerait 6000 ms fois (39 000 000/46656) = 5 015 432 ms au lieu de 22 000 ms et là je ne comprends plus rien. On dirait que ces tests n'ont pas été effectués sur le même ordi.

    J'allais oublier : Les durées d'éxécution citées dans mes messages résultent aussi de l'utilisation d'un Pentium III - 1.13 GHz. Toute comparaison avec des tests effectués sur une autre bécane nécessite de tenir compte d'un facteur de correction sinon la comparaison perd son sens.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  2. #42
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Elle est suivie cette discussion, les algos fusent

    J'ai fait une nouvelle version itérative minimisant les allocations mémoires (une seule en fait) avec quadruple boucle for

    avec 'abcdef' sur un mot de 10, ça fait 60 466 176 possibilités ! (et un tableau de 604 661 760 de char !)
    trouvés en 7,75 sec ! (mais pour les afficher ... j'attends encore )
    (bon avec un Athlon64 3500+ )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    function possibilites3( Elts : string ; TailleMot : Cardinal   ) : TDynArrayC;
    var NbElts ,Hauteur : Cardinal; i,j,k,l, Limitej, Limitei : Cardinal;
    begin
       NbElts  := Length( Elts );
       Hauteur := Power( NbElts , TailleMot  );
       Result  := TDynArrayC.Create( Hauteur , TailleMot+1);
     
       for i := 0 to Hauteur - 1 do
       begin
         Result[i,TailleMot] :=  #0;
       end;
     
       Limitej := 1;
       Limitei := Hauteur div NbElts;
       for l := 0 to TailleMot - 1 do
       begin
        for j := 0 to Limitej-1 do
         for k := 0 to NbElts-1  do
          for i := 0 to Limitei-1 do
            Result[j*NbElts*Limitei + k*Limitei + i,l] := Elts[k+1];
        Limitei := Limitei div NbElts;
        Limitej := Limitej*NbElts;
       end;
     
     
    end;
    Code complet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    unit Unit2;
     
    interface
     
    uses
      Windows, Messages, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, XPMan, ComCtrls;
     
    type
      TDynArrayC = class(TObject)
      private
        FTab : PChar;
        FHauteur, FLargeur : cardinal;
        function  GetLigne( i : cardinal ): PChar;
        function  GetChar ( i , j : cardinal): char;
        procedure SetChar ( i , j : cardinal ; Valeur : char );
      public
        constructor Create( Hauteur , Largeur : cardinal );
        destructor Destroy; override;
        property Tab[i , j : cardinal] : char read GetChar write SetChar; default;
        property Ligne[i : cardinal] : PChar read GetLigne;
        property Hauteur : cardinal read FHauteur;
        property Largeur : cardinal read FLargeur;
      end;
     
      TMainForm = class(TForm)
        Memo: TMemo;
        ButtonTest: TButton;
        Panel: TPanel;
        EditChar: TEdit;
        EditTaille: TEdit;
        ProgressBar: TProgressBar;
        XPManifest1: TXPManifest;
        procedure ButtonTestClick(Sender: TObject);
        procedure EditTailleExit(Sender: TObject);
      private
        { Déclarations privées }
        Taille : cardinal ;
      public
        { Déclarations publiques }
      end;
     
    var
      MainForm: TMainForm;
     
    implementation
     
    uses
      SysUtils;
     
    {$R *.dfm}
     
     
    function Power( Base , Exp : Cardinal ) : Cardinal ;
    begin
      Result := 1;
      while Exp <> 0 do
      begin
        if Exp mod 2 = 1 then Result := Result * Base;
        Base := Base*Base;
        Exp := Exp div 2 ;
      end;
     
    end;
     
    function possibilites3( Elts : string ; TailleMot : Cardinal   ) : TDynArrayC;
    var NbElts ,Hauteur : Cardinal; i,j,k,l, Limitej, Limitei : Cardinal;
    begin
       NbElts  := Length( Elts );
       Hauteur := Power( NbElts , TailleMot  );
       Result  := TDynArrayC.Create( Hauteur , TailleMot+1);
     
       for i := 0 to Hauteur - 1 do
       begin
         Result[i,TailleMot] :=  #0;
       end;
     
       Limitej := 1;
       Limitei := Hauteur div NbElts;
       for l := 0 to TailleMot - 1 do
       begin
        for j := 0 to Limitej-1 do
         for k := 0 to NbElts-1  do
          for i := 0 to Limitei-1 do
            Result[j*NbElts*Limitei + k*Limitei + i,l] := Elts[k+1];
        Limitei := Limitei div NbElts;
        Limitej := Limitej*NbElts;
       end;
     
     
    end;
     
    { TDynArrayC }
    constructor TDynArrayC.Create(Hauteur, Largeur: cardinal);
    begin
       inherited Create;
       FHauteur := Hauteur;
       FLargeur := Largeur;
       GetMem(FTab,Hauteur*Largeur);
    end;
     
    destructor TDynArrayC.Destroy;
    begin
       FreeMem( FTab, FHauteur*FLargeur  );
       inherited;
    end;
     
    function TDynArrayC.GetChar(i, j: cardinal): char;
    begin
       Result := FTab[i*FLargeur+j];
    end;
     
    function TDynArrayC.GetLigne(i: cardinal): PChar;
    begin
       Result := @FTab[i*FLargeur];
    end;
     
    procedure TDynArrayC.SetChar( i, j: cardinal ; Valeur: char);
    begin
       FTab[i*FLargeur+j] := Valeur;
    end;
     
    procedure TMainForm.ButtonTestClick(Sender: TObject);
    var Resultat : TDynArrayC ; i : cardinal ; str : string;
        Start,Stop,Frequency : Int64; Temps : Extended;
    begin
       str := EditChar.Text ;
       if str = '' then Exit;   
     
       If Not QueryPerformanceCounter(Start) Then
          raise Exception.Create('Pas de compteur hautes performances.');
     
       Resultat := possibilites3( EditChar.Text , Taille );
     
       QueryPerformanceCounter(Stop) ;
       QueryPerformanceFrequency(Frequency);
       Temps := (Stop-Start)/Frequency ;
     
       if MessageDlg( IntToStr( Resultat.Hauteur ) + ' possibilités trouvées en '
                      +FloatToStr( Temps ) + sLineBreak  + 'Les afficher ?' ,
          mtInformation , [mbYes, mbNo],  0 ) <> mrYes then
       begin
         Resultat.Free;
         Exit ;
       end;
     
       ProgressBar.Min := 0;
       ProgressBar.Max := Resultat.Hauteur- 1 ;
       ProgressBar.Position := 0 ;
       ProgressBar.Visible := true;
     
       Memo.Lines.BeginUpdate;
       Memo.Clear;
       for i := 0 to Resultat.Hauteur- 1 do
        begin
          Memo.Lines.Add( Resultat.Ligne[i] );
          ProgressBar.Position := i;
        end;
       Memo.Lines.EndUpdate;
     
       ProgressBar.Visible := false;
       Resultat.Free;
    end;
     
    procedure TMainForm.EditTailleExit(Sender: TObject);
    begin
       try
         Taille := StrToInt64( EditTaille.Text );
       except
         Taille := 0;
       end;
       EditTaille.Text := IntToStr(Taille);
    end;
     
    end.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    object MainForm: TMainForm
      Left = 0
      Top = 0
      Caption = 'MainForm'
      ClientHeight = 471
      ClientWidth = 480
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Memo: TMemo
        Left = 0
        Top = 17
        Width = 480
        Height = 399
        Align = alClient
        BevelInner = bvNone
        BevelOuter = bvNone
        BorderStyle = bsNone
        Color = 15790288
        ReadOnly = True
        TabOrder = 0
        ExplicitTop = 0
        ExplicitHeight = 416
      end
      object Panel: TPanel
        Left = 0
        Top = 416
        Width = 480
        Height = 55
        Align = alBottom
        TabOrder = 1
        object ButtonTest: TButton
          Left = 1
          Top = 24
          Width = 478
          Height = 30
          Align = alBottom
          Caption = 'Test'
          TabOrder = 0
          OnClick = ButtonTestClick
        end
        object EditChar: TEdit
          Left = 1
          Top = 1
          Width = 240
          Height = 23
          Hint = 'Charact'#232'res possibles'
          Align = alLeft
          TabOrder = 1
        end
        object EditTaille: TEdit
          Left = 241
          Top = 1
          Width = 238
          Height = 23
          Hint = 'Taille des combinaisons'
          Align = alClient
          ParentShowHint = False
          ShowHint = True
          TabOrder = 2
          OnExit = EditTailleExit
          ExplicitLeft = 247
          ExplicitTop = -5
          ExplicitHeight = 39
        end
      end
      object ProgressBar: TProgressBar
        Left = 0
        Top = 0
        Width = 480
        Height = 17
        Align = alTop
        TabOrder = 2
        Visible = False
        ExplicitLeft = 120
        ExplicitTop = 160
        ExplicitWidth = 150
      end
      object XPManifest1: TXPManifest
        Left = 432
        Top = 32
      end
    end

  3. #43
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Intéressant algo, gb_68, mais Limitej n'aurait pas tendance à rester toujours à 1 ?

    ensuite
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       for i := 0 to Hauteur - 1 do
       begin
         Result[i,TailleMot] :=  #0;
       end;
    sur mon poste de bureau P4 3G, 500Mo, rien que cela met la minute pour faire les 60 millions de #0, alors comment peux tu avoir un calcul en 7s !

    et ton tableau fait 665127936 char, tu n'as pas compté les #0 !

    et sinon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j*NbElts*Limitei + k*Limitei + i
    pourrait devenir pour avoir moins d'opération asm

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (j*NbElts+k)*Limitei +i
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #44
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Suite des retouches au code de Bativir :

    - procedure EcritStringDansMemStream(MemStream: TMemoryStream; str : string); : virée vu qu'elle s'est réduite à une seule instruction disant MemStream.Write(PChar(str)^, length(str)); que j'ai placée à l'intérieur même de la récurse.

    En prime de la simplif du code cela a amélioré les résultats des tests de vitesse :

    - pour les 3125 "combinaisons" à partir de ABCDE : descendu de 10 millisec à 5 ms,

    - pour les 46656 "combinaisons" à partir de ABCDEF : descendu de 105 millisec à 75 ms,

    - pour les 823543 "combinaisons" à partir de ABCDEFG : 6825 ms avant la simplification du code ce cas arrivait à saturer la mem-disponible.
    (durées pour Pentium III - 1,13 GHz).

    Comme le code s'est simplifié j'y ai ajouté la procedure LectureAffichageExtraitStream(indiceDeb, Nombre : integer; Dest : tRichEdit);
    qui a affiche les Items du Stream en Nombre à partir de indiceDeb.
    A toutes fins utiles, ci-joint le code retouché.

    Remarque sur le nombre total de "combinaisons" "possibles" :
    Avec le code précité, le nombre de "combinaisons" obtenues à partir des "p" premiers caractères de la chaine 'A..W0..9' est chaque fois égal à p^p (p puissance p) ce qui conduit à un total de possibilités, avec ces 33 caractères, égal à :

    S1 = 1 + 2^2 + 3^3 + 4^4 + 5^5 ... + p^p ... + 33^33
    ...ça en fait déjà beaucoup ... mais comme il s'agit toujours des "p premiers" caractères il faudrait également ajouter à chaque cas de figure le nombre de "combinaisons" que l'on peut obtenir avec les "p suivants".
    Exemple : pour p = 4 les "combinaisons" résultent d'arrangements à partir de 'ABCD' et qui s'élèvent à 4^4 = 256 mais en poussant le curseur d'un cran vers la droite il y aussi les 4^4 qui proviennent des "4 suivants" c.à.d 'BCDE', autant de 'CDEF, ... et ce jusquà '6789'.
    Et ceci est valable au moins de p = 2 jusqu'à p = 32 ... mais comme on sature déjà bien avant.

    Voiçi le code précité:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    // -------- Combinaisons-arrangements avec répétitions -------------------------
     
    var       streamC    : TMemoryStream;
              nbCara     : integer;  // nbre de caractères par Item
              itemsCount : longint;  // nbre d'Items dans le StreamC
              ChronoR    : oChrono;  // chronomètre
     
    procedure Combination(NbrCaracters: Integer; CombinCaracters, Caracters: string);
    var       i: Integer;
    begin     if NbrCaracters = 0
              then begin //Form1.Memo1.Lines.Add(CombinCaracters); remplacé par :
                         streamC.Write(PChar(CombinCaracters)^, length(CombinCaracters));
              end else
              begin for i := 1 to Length(Caracters)
                    do Combination(NbrCaracters-1, CombinCaracters+Caracters[i], Caracters);
              end;
    end;
     
    procedure TForm1.bCombEtRepetesClick(Sender: TObject);
    var       Caracters: string;
    begin     red1.Clear;
              edRes.text:='';
              // ----------------
              ChronoR.Top(labChronoR);
              //nbCara :=2; //<      4 Combinaisons-Arrangements-avec-répètes
              //nbCara :=3; //<     27 Combinaisons
              //nbCara :=4; //<    256 Combinaisons    Délais d'éxec pour Pentium III 1.13 GHz :
              //nbCara :=5; //<   3125 Combinaisons    5 millisec avec TMemoryStream et 3104 milli avec RichEd
              //nbCara :=6; //<  46656 Combinaisons   75 millisec avec TMemoryStream
              nbCara :=7;   //< 823543 Combinaisons 6825 millisec avec TMemoryStream
              //Pour nbCara :=8;  msg plus de mémoire lors de l'extension du flux !
              Caracters:=copy('ABCDEFGHIJKLMNOPQRSTUVW0123456789',1,nbCara);
              if streamC<>nil
              then streamC.Free
              else streamC:=TMemoryStream.create;
              Combination(nbCara,'', Caracters);
              ChronoR.Mis;
              // ----------------
              itemsCount:= StreamC.Size div nbCara;
              edRes.text:= intToStr(itemsCount)
                           +' Combinaisons avec '+intToStr(nbCara)+'caractères';
    end;
     
    procedure LectureAffichageExtraitStream(indiceDeb, Nombre : integer; Dest : tRichEdit);
    //        Affiche les Items en Nombre à partir de indiceDeb
    var       Item : string; i,j : integer; c : char;
    begin     if (Nombre<=0) or (indiceDeb<0) or (indiceDeb>ItemsCount-1) then EXIT;
              if (indiceDeb + Nombre) > ItemsCount - 1
              then Nombre := ItemsCount - 1 - indiceDeb;
              StreamC.Position:=indiceDeb*nbCara;
              for i:=1 to Nombre do
              begin Item:='';
                    for j:=1 to nbCara do begin StreamC.Read(c,1); Item:=Item+c; end;
                    Dest.Lines.Add(Item);
              end;
    end;
     
    procedure TForm1.bAfficherExtraitClick(Sender: TObject);
    begin     red1.Clear;
              // Ex : Affichage du 10ième :
              LectureAffichageExtraitStream(9, 1, Red1);
              // Ex : Affichage d'une dixaine à partir du 1er :
              LectureAffichageExtraitStream(0, 10, Red1);
    end;
     
    procedure TForm1.bAfficheToutClick(Sender: TObject);
    begin     red1.Clear;
              LectureAffichageExtraitStream(0, ItemsCount, Red1);
    end;
    Bonne continuation.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  5. #45
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    Bonjour Gilbert

    Pas d'accord avec ton calcul de S1, l'ensemble des éléments à combiner ne s'accroît pas, il est de taille fixe, c'est la taille des combinaisons obtenus qui
    varie. Si l'ensemble de départ est ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789, le cardinal vaut 36 et S1 doit s'exprimer sous la forme :
    S1 = 36^0 + 36^2 + 36^3 + 36^4 + 36^5 ... + 36^p ... + 36^33
    ce qui n'arrange pas notre problème.

    L'avantage de l'algorithme numéral que j'ai proposé et de permettre d'atteindre une combinaison particulière à partir d'un entier. Si l'ion introduit en plus la taille de la combinaison, tout élément peut être atteint à partir de la connaissance de deux entiers. Cela peut être intéressant.

    Sinon, elle est sympa l'optimisation de code mais comme je le disais, il faut se méfier des mesures de performances qui sont parfois fortement variable entre deux exécutions dans un environnement (en fonction de la charge instantanée du processeur)

    cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  6. #46
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Je vous rappelle le prototype de fonction demandé par BATIVIR :
    Et à part quelques Algo, comme le mien ou celui de E-Ric, personne ne prend en compte la Taille de la Combinaison (k) qui défini le nombre d'arrangements possibles dans un Ensemble (n = Lengtg(Ensemble)) donc n^k (arrangement avec répétition, il existe d'autres combinatoire avec d'autres formules, comme les Permutations sans répétition = n!, Permutations avec répétition = trop compliqué, Arrangements sans répétition = n! / (n - k)!, Combinaison avec/sans répétition = d'autres formules ) ...

    je n'ai pas bien compris voir histoire de S1 = p^p-n + ... + p^p-2 + p^p-1 ?


    Juste pour rappel, le nombre obtenu par "(Stop-Start)/Frequency" est en secondes ! j'ai l'impression qu'il y a des mélanges à ce sujet aussi !

    Ensuite

    - pour les 823543 "combinaisons" à partir de ABCDEFG : avec le code de Aujourd'hui 14h15 Gilbert Geyer, j'ai 5015 à 5127 ms pour le calcul

    - pour l'Arrangement de longeur 7 sur ABCDEFG (donc 823543) avec l'objet TCombinatoireEngine j'ai entre 52 et 57 ms pour le calcul,

    Et le Stream.Write c'est lent car c'est aussi de réallocation, alors que les Algos par FreeMem alloue une seule et unique fois !

    Maintenant faire 8 sur ABCDEFG, c'est 440 ms, faire 9 sur ABCDEFG c'est bcp trop long (j'ai pas eu la patience ...) car ma machine n'a que 512Mo, alors que cela en occupe dans les 350Mo, plus Delphi et XP, cela swappe énormément, une machine de 1Go aurait une performance accrue pour ce genre de calcul ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #47
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bonjour E-ric,

    Attention le calcul de S1 de mon message précédent était précédé par l'introduction disant "Avec le code précité" :

    Et ce code considère que :
    - si l'ensemble de départ est ABCDEFGHIJKL...W0123456789 (ensemble fixe),
    - si le sous-ensemble des "p" éléments à combiner est chaque fois pris égal aux "p premiers caractères" de l'ensemble de départ (vu l'instruction Caracters:=copy('AB..89',1,nbCara))
    - vu la procedure Combination(NbrCaracters: Integer; CombinCaracters, Caracters: string) qui produit des "combinaisons" de longueur égale à "p";
    - alors la rafale de combinaisons produites est égale à p^p.
    En plus l'affichage du itemsCount indique à chaque fois un nombre égal à p^p.
    ... et comme on peut faire varier p de 1 à 33 (pas 36 car il n'y a pas X,Y et Z dans la donne initiale de Bativir) cela conduit à la série S1 = 1 + 2^2 + ... p^p + (p+1)^(p+1) ... 33^33.

    Par contre je ne dis pas que la forme que tu donnes à S1 est fausse vu qu'elle découle certainement de ton algorithme numéral.
    Et comme tu dis "ce qui n'arrange pas notre problème" à son sujet, j'ajouterais que de toute façons dès qu'on pénètre l'analyse combinatoire on atteint très rapidement le plafond des possibilités des bécanes : p^p grimpe encore plus vite que la fonction exponentielle ( e^x < x^x pour x supérieur à e = 2,7182).

    Mais je me demande si ce sujet préoccupe encore Bativir depuis qu'il a mis le tag résolu ?.

    En tous cas merci pour la rectification du code autour de MemStream.Write() car là au moins c'est un enseignement récupérable au profit d'autres applis car je n'entrevois pas d'utiliser ni les codes des anagrammes (c'est juste amusant 5 min) ni les codes des combinaisons-arrangments, c'est surtout le thème des optimisations qui m'intéresse dans les discussions.
    A+
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  8. #48
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Ah d'accord, vous voulez savoir le nombre de combinaison total sur ABC...789 mais c'est impossible puisque la longueur de la combinaison est infini tu peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB


    sinon, je viens de changer le code, justement à l'instant

    - pour l'Arrangement de longeur 7 sur ABCDEFG (donc 823543) avec l'objet TCombinatoireEngine j'ai entre 26 et 28 ms pour le calcul,

    - pour l'Arrangement de longeur 8 sur ABCDEFG (donc 823543) avec l'objet TCombinatoireEngine j'ai entre 206 et 216 ms pour le calcul,

    40% d'optimtisation en manipulant du PChar au lieu d'un String pour "ABCDEFG", et en précalculant mes offset au lieu de faire des multiplications couteuses ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    type
      TCombinatoireEngine = class(TObject)
      private
        FData: Pointer;
        FCount: Integer;
        FItemLength: Integer;
        function GetItems(const Index: Integer): string;
      public
        destructor Destroy; override;
        function CalculArrangementsAvecRepetition(NbEmplacements: Integer; Objets: string): Boolean;
        procedure SaveToFile(const FileName, Delimiter: string);
        property Items[const Index: Integer]: string read GetItems;
        property Count: Integer read FCount;
        property ItemLength: Integer read FItemLength;
      end;
     
    { TCombinatoireEngine }
     
    function TCombinatoireEngine.CalculArrangementsAvecRepetition(NbEmplacements: Integer; Objets: string): Boolean;
    var
      NbObjets: Integer;
      OffSet: Integer;
      Threshold, iStep: Integer;
      IndexData: Integer;
      pObjets, pObjetsOff, pObjetsOffMax, pData, pDataOff : PChar;
    begin
      Result := True;
      if Assigned(FData) then
        FreeMem(FData);
     
      FItemLength := NbEmplacements;
      NbObjets := Length(Objets);
      FCount := Trunc(Math.IntPower(NbObjets, NbEmplacements));
     
      GetMem(FData, FCount * FItemLength);
      pObjets := PChar(Objets);
      pObjetsOff := pObjets;
      pObjetsOffMax := pObjets;
      Inc(pObjetsOffMax, NbObjets);
      pData := PChar(FData);
     
      Threshold := FCount;
      for OffSet := 0 to FItemLength - 1 do
      begin
        Threshold := Threshold div NbObjets;
        iStep := 0;
        pDataOff := pData;
        for IndexData := 0 to FCount - 1 do
        begin
          pDataOff^ := pObjetsOff^;
     
          Inc(pDataOff, FItemLength);
          Inc(iStep);
          if iStep = Threshold then
          begin
            iStep := 0;
            Inc(pObjetsOff);
            if pObjetsOff = pObjetsOffMax then
              pObjetsOff := pObjets;
          end;
        end;
        Inc(pData);
      end;
    end;
     
    procedure TCombinatoireEngine.SaveToFile(const FileName, Delimiter: string);
    var
      OutFile: file;
      IndexData: Integer;
    begin
      AssignFile(OutFile, FileName);
      ReWrite(OutFile, 1);
      try
        if Delimiter = '' then
        begin
          BlockWrite(OutFile, PChar(FData)^, FCount * FItemLength);
        end
        else
        begin
          for IndexData := 0 to FCount - 1 do
          begin
            BlockWrite(OutFile, PChar(Integer(FData) + IndexData * FItemLength)^, FItemLength);
            BlockWrite(OutFile, Delimiter[1], Length(Delimiter));
          end;
        end;
      finally
        CloseFile(OutFile);
      end;
    end;
     
    destructor TCombinatoireEngine.Destroy;
    begin
      if Assigned(FData) then
        FreeMem(FData);
     
      inherited;
    end;
     
    function TCombinatoireEngine.GetItems(const Index: Integer): string;
    begin
      if Index < FCount then
      begin
        SetLength(Result, FItemLength);
        CopyMemory(@Result[1], Pointer(Integer(FData) + Index * FItemLength), FItemLength);
      end else
      begin
        raise EListError.CreateFmt(SListIndexError, [Index]);
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #49
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Bigre, ça a encore bougé ... et des messages rédigés en parallèle.
    Mais à chaque jour suffit sa peine ... réponse à demain.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  10. #50
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    Variation sur l'algorithme dit "numéral"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    procedure TCombinationFrm.SafeCombinationNumeral(Tab: String; CombSize: Integer);
    var
      I, MaxValue, Value: Int64;
      TabSize, J : Integer;
      FS: TFileStream;
      Combin: String;
     
    const
      CombinatFileName = 'C:\Temp\Combinat.txt';
     
    begin
      if FileExists(CombinatFileName) then
        FS := TFileStream.Create(CombinatFileName, fmOpenWrite)
      else
        FS := TFileStream.Create(CombinatFileName, fmCreate);
      try
        TabSize := Length(Tab);
        MaxValue := _Power(TabSize, CombSize);
        FS.Size := MaxValue * (CombSize + 2);
        FS.Seek(0, soBeginning);
        SetLength(Combin, CombSize+2);
        Combin[CombSize+1] := #13;
        Combin[CombSize+2] := #10;
        I := 0;
        while I < MaxValue do
        begin
          Value := I;
          for J := CombSize downto 1 do
          begin
            Combin[J] := Tab[Value mod TabSize + 1];
            Value := Value div TabSize;
          end;
          FS.Write(Combin[1], CombSize+2);
          Inc(I);
        end;
      finally
        FS.Free;
      end;
    End;
     
    procedure TCombinationFrm.btnAlgoNumeralClick(Sender: TObject);
    var
      d: TDateTime;
    begin
      d := Now;
      if (Edit.Text = '') or (Edit.SelLength = 0) then
        exit;
      SafeCombinationNumeral(Edit.Text, Edit.SelLength);
      ShowMessage('Durée = ' + FormatDateTime('hh:nn:ss:zzz', Now - d));
    End;
    Sur mon PC de travail (c'est pas une formule 1, < 3Ghz et 1 Go RAM), avec pas mal de tâche de fond et je précise que mon implémentation enregistre sur le disque pas en mémoire.

    J'obtiens des performances sympa, pour ABCDEFG (ensemble de test et 7 caractère de taille de combinaison) : 1370 ms.

    Cela me paraît bizarre par rapport à vos perf, vous pourriez le tester.

    Il faut modifier la démo que j'ai déjà transmis.

    cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  11. #51
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    3Ghz + 1Go, tu peux donc calculer plus de combinaison que mon poste 3Ghz + 512Mo, car tu ne swappes pas la mémoire ...

    Sinon, Now, c'est pas toujours terrible pour les mesures

    Alors
    si le fichier n'existe pas c'est 6.5s à 7s
    si le fichier existe déjà c'est 4.5s

    Avec mon Objet, c'est 33 ms de calcul, pour le fichier (brut sans séparateur 100ms, avec séparateur c'est 9s, car j'écrit 7+2 et non 9)

    Il est évident que Ton Algo est la Solution, Tu génère le fichier, ensuite suffit de jouer avec un seek dans le fichier pour récupérer ses items, cela prend pas de mémoire, ton algo est ultra simple, astucieux le coup du Modulo et Quotient, ... quel fut ton cheminement pour trouver cette formule ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #52
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    Bonsoir

    dernière réponse avant de partir.
    J'ai trouvé encore plus rapide en employant la fonction DivMod (qui malheureusement emplois des Word):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    procedure TCombinationFrm.SafeCombinationNumeral(Tab: String; CombSize: Integer);
    var
      I, MaxValue, TabSize, J : Integer;
      Value, Q, R: Word;
      CombSize2: Integer;
      S: TFileStream;
      Combin: String;
     
    const
      CombinatFileName = 'C:\Temp\Combinat.txt';
     
    begin
      if FileExists(CombinatFileName) then
        S := TFileStream.Create(CombinatFileName, fmOpenWrite)
      else
        S := TFileStream.Create(CombinatFileName, fmCreate);
      try
        TabSize := Length(Tab);
        MaxValue := _Power(TabSize, CombSize);
        S.Size := MaxValue * (CombSize + 2);
        S.Seek(0, soBeginning);
        SetLength(Combin, CombSize+2);
        Combin[CombSize+1] := #13;
        Combin[CombSize+2] := #10;
        CombSize2 := CombSize+2;
        I := 0;
        while I < MaxValue do
        begin
          Value := I;
          for J := CombSize downto 1 do
          begin
            DivMod(Value, TabSize, Q, R);
            Combin[J] := Tab[R+1];
            Value := Q;
          end;
          S.Write(Combin[1], CombSize2);
          Inc(I);
        end;
      finally
        S.Free;
      end;
    End;
    Avec un TMemoryStream, je divise le temps par 5 environ (270 ms environ sans copie sur le disque).

    L'idée de numération m'est venue simplement en regardant les résultats de mon premier algo (itératif), il suffit de généraliser ce que l'on fait quand on compte :

    0001
    0002
    ...
    0010
    0011
    0012

    etc...

    Si tu as déjà réalisé un algorithme de changement de base de numération (par exemple de base 10 à base 16) alors le problème est simple...
    Ma base de numération est ABCDEFG et j'affiche toutes les valeurs de AAAAAA jusqu'à GGGGGGG.

    cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  13. #53
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    La dernière est buggée, mince !

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  14. #54
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Excellente l'observation de l'alphabet 012345789, ... et considérer l'arrangement comme un calcul de base !

    Le TMemoryStream est bien pour un faible volume (moins d'un 1/5 eme de la mémoire de la machine) ensuite le fichier est la solution ...

    Sinon, le mieux reste le calcul en direct effectivement ... je n'ai pas testé, j'ai juste modifié sur le Forum, le code d'E-Ric, ainsi l'on peut demandé à la fonction n'importe quel item, ainsi on peut genre si l'on veut juste une fenêtre de combinaison ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    GetArrangement(Objets: string; LongueurArrangement: Integer; Index: Integer): string;
    var
      J: Integer;
      TabSize: Integer;
    begin
      SetLength(Result, LongueurArrangement);
      TabSize := Length(Objets);
      for J := LongueurArrangement downto 1 do
      begin
        Result[J] := Objets[Indexmod TabSize + 1];
        Index:= Indexdiv TabSize;
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  15. #55
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    L'idée d'E-ric d'occuper le disque plutôt que la mémoire est effectivement intéressante vu qu'elle vient de concourir à révéler également les performances du "numéral" . En plus je suis surpris par la rapidité d'éxécution car je m'attendais à ce qu'un TFileStream soit nettement plus lent qu'un TMemoryStream. Pour apprécier cette rapidité je suis parti des 1370 ms annoncés Hier à 17h 46 par E-ric pour les Items produits avec ABCDEFG et son 3Ghz ... ce qui pourrait donner avec ma 2-Chevaux cadencée à 1.13 MHz via une règle de trois (faute de mieux) 3162 ms ce qui est de l'ordre de deux fois plus rapide que les 6825 ms mesurés pour le même cas de figure cité dans mons message d'Hier 14h15.
    J'étais persuadé que la mémoire vive était toujours plus rapide que les transferts vers le disque dur ... à moins que je ne sois en-train de comparer des tomates à des carottes ... ou à moins que de passer en "numéral" ne compense les différences de rapidité write-mem-vive/write-disque.

    E-ric a dit "...fonction DivMod (qui malheureusement emplois des Word)" : et qui qui malheureusement n'existe pas dans l'aide de mon Delphi-5. D'où Exit les essais sur la dernière version.
    Bon week-end.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  16. #56
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    La mémoire est plus rapide tant qu'on ne dépasse pas la capacité réelle de celle-ci, du moment où la mémoire virtuelle entre en action, les performances dégringolent car il y a des échanges permanent entre la mémoire et le disque. Cette situation est rapidement atteinte dans les environnements multi-tâches car les processus ont chacun leur exigences en mémoire.

    En ce qui concerne l'algorithme "numéral" actuel, je compte l'optimiser en supprimant les opérations div et mod qui consomme de la CPU. pour ce faitre je compte revenir en partie sur le principe de l'algorithme itératif.

    cdlt

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  17. #57
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    Citation Envoyé par Gilbert Geyer
    E-ric a dit "...fonction DivMod (qui malheureusement emplois des Word)" : et qui qui malheureusement n'existe pas dans l'aide de mon Delphi-5. D'où Exit les essais sur la dernière version.
    Bon week-end.
    Tu veux le code ("volé" dans la VCL) ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    procedure DivMod(Dividend: Integer; Divisor: Word;
      var Result, Remainder: Word);
    asm
            PUSH    EBX
            MOV     EBX,EDX
            MOV     EDX,EAX
            SHR     EDX,16
            DIV     BX
            MOV     EBX,Remainder
            MOV     [ECX],AX
            MOV     [EBX],DX
            POP     EBX
    end;

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  18. #58
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 946
    Points
    3 946
    Par défaut
    Le remplacement de Divmod ne pose aucun problème, il suffit d'utiliser Div et Mod successivement.

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  19. #59
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 263
    Points
    3 263
    Par défaut
    Merci E-ric pour le code de DivMod

    Tu dis "En ce qui concerne l'algorithme "numéral" actuel, je compte l'optimiser en supprimant les opérations div et mod qui consomme de la CPU. pour ce faire je compte revenir en partie sur le principe de l'algorithme itératif".
    Je constate que tu turbines à fond sur ce sujet.

    Pour ma part j'envisageais de faire un essai de remplacement du MemoryStream par un FileStream pour me fixer les idées à propos des comparaisons des vitesses d'éxécution mais je passe plus de temps sur le Forum ou ailleurs.

    Bon week-end;
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  20. #60
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Pour ma part j'envisageais de faire un essai de remplacement du MemoryStream par un FileStream pour me fixer les idées à propos des comparaisons des vitesses d'éxécution mais je passe plus de temps sur le Forum ou ailleurs.
    Gilbert Geyer, ne t'embète pas, E-Ric a déjà donné l'explication, de la Mémoire lente à trop grand volume à cause du SWAP, il suffit de mettre la colonne Erreur de Page dans le Gestionnaire des Taches, les Algo tel que le mien en memoire via pointer ou TMemoryStream en font bcp, et c'est là d'où vient la lenteur car la mémoire qui était censé être en RAM est en fait sur le DD (Fichier d'Echange) ... Voilà pourquoi à gros volume, le transfert vers fichier est aussi rapide que la mémoire car celle ci est tout simplement en train de faire aussi du transfert de fichier avec en plus des relectures ...

    La mémoire est plus rapide tant qu'on ne dépasse pas la capacité réelle de celle-ci, du moment où la mémoire virtuelle entre en action, les performances dégringolent car il y a des échanges permanent entre la mémoire et le disque
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 26/02/2009, 14h51
  2. Test possibilité de mise à jour.
    Par brsoft.org dans le forum Accès aux données
    Réponses: 3
    Dernier message: 05/06/2007, 18h54
  3. $_post["$test"] c possible ??
    Par fongus dans le forum Langage
    Réponses: 6
    Dernier message: 07/06/2006, 20h56
  4. Longue boucle ?
    Par choas dans le forum Langage
    Réponses: 9
    Dernier message: 11/03/2006, 20h19
  5. Réponses: 4
    Dernier message: 09/12/2005, 08h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo