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 :

[Défi] Le Défi Delphi n°5 : Le Sudoku solver


Sujet :

Delphi

  1. #181
    Membre averti
    Avatar de Félix Guillemot
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    149
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 149
    Points : 386
    Points
    386
    Par défaut
    PSudokuSolverDataStruct c'est un Pointeur de Record TSudokuSolverDataStruct
    J'avais bien compris

    ce n'est pas un objet, sinon j'aurais utiliser une TObjectList et non une TList ! Je te le dis à l'ancienne !
    Moi aussi j'utilise les TList, c'est très bien

    Avec ce que tu as écrit c'est "Transtypage Incorrect" garanti !
    Je ne vois vraiment pas pourquoi, je le fais sans arrêt, mais puisque tu le dis...
    Sois je n'ai pas saisi qq chose, soit tu te trompes, mais je peux te fournir des tonnes d'exemples de ce type. D'ailleurs, mon code du SudokuSolver en est gavé.

    je parcours une TList

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i := 0 to MaList.count - 1 do
    begin
      TMonObjet(MaList[i]).MaProprietePropreAMonObjet := 0;
    end;

  2. #182
    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
    Tu donne un exemple avec des Objets pas avec des record

    Sinon, tu as raison, pour un pointeur sur record tu peux faire le transtypage directement, je ne le fais pas, j'utilise plutôt mon Type pointeur puis je le déférence pour une question de logique dans le code ...

    Je reprends le code que tu m'a donné à tester par MP, comme tu ne déclare pas de Type Pointeur dédié, tu es obligé de faire ces vilaines choses
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    type
      TMyRecord = record
        PropStr : String;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var 
      MyRecord : TMyRecord; // Allocation d'un Record inutile
      iCpt     : integer;
    ...
      for iCpt := 1 to 10 do
      begin
        New(Pointer(MyRecord));
        MyRecord.PropStr := 'chaine N°' + inttostr(iCpt);
        FMyList.add(Pointer(MyRecord)); 
      end;
      New(Pointer(MyRecord)); // Allocation d'un Record pour que le "end" ne libère pas le dernièr ajouté
    end;
    Le Premier MyRecord celui créé par le "begin" n'est pas libéré puisque le "end" va en libéré un autre, ça ne ferait pas une petite fuite de mémoire ?

    Voici le code proprement écrit avec un Type Pointeur dédié
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type
      PMyRecord = ^TMyRecord;
      TMyRecord = record
        PropStr : String;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var 
      MyRecord : PMyRecord ; // Juste un Pointeur
      iCpt     : integer;
    ...
      for iCpt := 1 to 10 do
      begin
        New(MyRecord);
        MyRecord.PropStr := 'chaine N°' + inttostr(iCpt);
        FMyList.add(MyRecord); 
      end;
    end;

    Bien sur chaque New doit être libére par un Dispose, comment écris-tu la libération ?



    en fait PSudokuSolverDataStruct est un pointeur de tableau fixe de structure (d'où la confusion, désolé) ... est là le transtypage puis déférencement est obligatoire, excuse-moi de t'avoir indui en erreur ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      TSudokuSolverCellItem = record
        ...
      end;
      TSudokuSolverDataStruct = array[1..9, 1..9] of TSudokuSolverCellItem;
      PSudokuSolverDataStruct = ^TSudokuSolverDataStruct;
    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

  3. #183
    Membre averti
    Avatar de Félix Guillemot
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    149
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 149
    Points : 386
    Points
    386
    Par défaut
    Tu donne un exemple avec des Objets pas avec des record
    Tu plaisantes ? J'ai fait exprès de déclarer un record !
    C'est quoi ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    type
      TMyRecord = record
        PropStr : String;
    end;


    Je reprends le code que tu m'a donné à tester par MP, comme tu ne déclare pas de Type Pointeur dédié, tu es obligé de faire ces vilaines choses
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    type
      TMyRecord = record
        PropStr : String;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var 
      MyRecord : TMyRecord; // Allocation d'un Record inutile
      iCpt     : integer;
    ...
      for iCpt := 1 to 10 do
      begin
        New(Pointer(MyRecord));
        MyRecord.PropStr := 'chaine N°' + inttostr(iCpt);
        FMyList.add(Pointer(MyRecord)); 
      end;
      New(Pointer(MyRecord)); // Allocation d'un Record pour que le "end" ne libère pas le dernièr ajouté
    end;
    Le Premier MyRecord celui créé par le "begin" n'est pas libéré puisque le "end" va en libéré un autre, ça ne ferait pas une petite fuite de mémoire ?
    Le premier record est liberé puisqu'il appartient à une procédure locale.

    Pour ce qui est des fuites de mémoire :
    J'ai justement vérifié avant de te donner le code

    A partir de D2006, il y a une variable globale que tu peux mettre à true en début de programme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ReportMemoryLeaksOnShutDown := true;
    Le résultat est qu'à la fin du processus, il te fait un rapport des fuites de mémoires, et là il n'y en a pas. C'est l'avantage d'avoir les dernières versions de Delphi (je suis sous 2007)

    Je t'ai envoyé un MP pour ne pas polluer le débat du Sudoku avec ces détail techniques, et toi tu me le remets ici

  4. #184
    Membre averti
    Avatar de Félix Guillemot
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    149
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 149
    Points : 386
    Points
    386
    Par défaut Vacances
    Bon, les amis,

    Je pars demain matin en vacances, je reviens le 03/08 donc amusez vous bien d'ici là, et ne vous faites pas une entorse au cerveau.
    Pensez à sortir, prendre l'air, faire un peu de luminothérapie, etc.

    A+

    Félix.

  5. #185
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    en fait PSudokuSolverDataStruct est un pointeur de tableau fixe de structure (d'où la confusion, désolé) ... est là le transtypage puis déférencement est obligatoire, excuse-moi de t'avoir indui en erreur ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      TSudokuSolverCellItem = record
        ...
      end;
      TSudokuSolverDataStruct = array[1..9, 1..9] of TSudokuSolverCellItem;
      PSudokuSolverDataStruct = ^TSudokuSolverDataStruct;
    Même dans ce cas là, il faut savoir qu'on peut parfaitement écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var
      SudokuSolverDataStruct : PSudokuSolverDataStruct;
    { avec  FCores : TList déjà créée et remplie }
     
    begin
      ....
      SudokuSolverDataStruct := FCores[ACore]; // He oui, on affecte un Pointer générique, à un pointeur typé ! Le compilo accepte bien qu'il ne devrait pas.
      Assert(SudokuSolverDataStruct[5, 4].Valeur = SudokuSolverDataStruct^[5, 4].Valeur);
    De cette façon, pas besoin de Cast, de AS, de @ ni de ^.

  6. #186
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Félix Guillemot Voir le message
    Tu plaisantes ? J'ai fait exprès de déclarer un record !
    C'est quoi ça :
    (zap)
    Pour ce qui est des fuites de mémoire :
    J'ai justement vérifié avant de te donner le code
    (zap)
    non il n'y a pas de fuite mémoire, mais l'usage que tu fais du record est des plus étrange

    d'ailleurs il suffit de changer le record pour que ça ne compile plus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TForm1.FormCreate(Sender: TObject);
    type
      TMonRecord = record
        PropStr: string;
        PropInt: Integer;
      end;
    var
      MonRecord: TMonRecord;
    begin
      New(Pointer(MonRecord));
      MonRecord.PropStr := 'Hello';
    end;
    je vais voir ça plus tard, j'ai pas le temps
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #187
    Membre averti
    Avatar de Félix Guillemot
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    149
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 149
    Points : 386
    Points
    386
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    non il n'y a pas de fuite mémoire, mais l'usage que tu fais du record est des plus étrange

    d'ailleurs il suffit de changer le record pour que ça ne compile plus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TForm1.FormCreate(Sender: TObject);
    type
      TMonRecord = record
        PropStr: string;
        PropInt: Integer;
      end;
    var
      MonRecord: TMonRecord;
    begin
      New(Pointer(MonRecord));
      MonRecord.PropStr := 'Hello';
    end;
    je vais voir ça plus tard, j'ai pas le temps
    Tu n'as pas suivi la discussion:

    Perso, je me fous des records, j'utilise TObject
    Et c'était juste un exemple pour montrer à SHailLe Troll le transtypage pour éviter les ^ , @, etc qui sont des façons de programmer d'autrefois.
    Moi non plus, je n'ai pas le temps, et surtout de voir pourquoi quand tu changes mon code ça ne compile pas !

  8. #188
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Félix Guillemot Voir le message
    Tu n'as pas suivi la discussion:

    Perso, je me fous des records, j'utilise TObject
    Et c'était juste un exemple pour montrer à SHailLe Troll le transtypage pour éviter les ^ , @, etc qui sont des façons de programmer d'autrefois.
    Moi non plus, je n'ai pas le temps, et surtout de voir pourquoi quand tu changes mon code ça ne compile pas !
    certes, mais ce code me choque

    1) il compile car TMonRecord a une taille de 4 octets, donc Pointer(MonRecord) est acceptable. Il suffit de faire un record d'une taille différence pour que ça ne compile plus

    2) je me suis demandé ce que pouvait bien comprendre Delphi à un New() sur un Pointer !

    et bien la réponse est assez surprenante, car New(p) avec p : Pointer fait appel à GetMem(0) ! ça renvoie donc un pointeur nil
    il suffit d'afficher la fenêtre CPU pour le vérifier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ; New(Pointer(MonRecord))
      xor eax,eax
      call @GetMem
    si je reprend le code on obtient ceci :
    Code delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      New(Pointer(MyRecord)); // place nil dans MyRecord.PropStr !
      MyRecord.PropStr := 'chaine N°' + inttostr(iCpt); // alloue une chaine puisqu'elle est vide
      FMyList.add(Pointer(MyRecord));  // copie la chaine dans la StringList
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #189
    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
    Citation Envoyé par Franck SORIANO Voir le message
    Même dans ce cas là, il faut savoir qu'on peut parfaitement écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    var
      SudokuSolverDataStruct : PSudokuSolverDataStruct;
    { avec  FCores : TList déjà créée et remplie }
     
    begin
      ....
      SudokuSolverDataStruct := FCores[ACore]; // He oui, on affecte un Pointer générique, à un pointeur typé ! Le compilo accepte bien qu'il ne devrait pas.
      Assert(SudokuSolverDataStruct[5, 4].Valeur = SudokuSolverDataStruct^[5, 4].Valeur);
    De cette façon, pas besoin de Cast, de AS, de @ ni de ^.
    Tout à fait, mais dans mon cas, j'aurais besoin d'écrire plus long par rapport à mon code d'origine, juste pour retirer le transtypage ne ensuite le déférencement pour le passage de procédure reste nécessaire ...

    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
    {* -----------------------------------------------------------------------------
    Accesseur de CoreCellDummies
    ------------------------------------------------------------------------------ }
    function TSudokuSolver.GetCoreCellDummies(ACore: Integer; ACol, ARow: Byte): TByteDynArray;
    var
      SudokuSolverDataStruct : PSudokuSolverDataStruct;
    begin
      if FCoreStored then
      begin
        SudokuSolverDataStruct := FCores.Items[ACore];  
        Result := BuildCellDummies(SudokuSolverDataStruct^, ACol, ARow); // Le déférencement est nécessaire quand même
      end 
      else
        Result := CellDummies[ACol, ARow];
    end;
    Citation Envoyé par Félix Guillemot Voir le message
    Je t'ai envoyé un MP pour ne pas polluer le débat du Sudoku avec ces détail techniques, et toi tu me le remets ici
    Pour la fuite mémoire, effectivement, on a de la chance, Delphi est fort pour allouer au bon moment (comme la 1ere affectation semble-t-il) mais tu avoues qu'allouer un Nouveau pointeur APRES la boucle c'est juste le truc le plus incohérent que possible ?


    Sinon, personne n'a évoqué comment faire les Dispose !


    Citation Envoyé par Paul TOTH Voir le message
    certes, mais ce code me choque

    1) il compile car TMonRecord a une taille de 4 octets, donc Pointer(MonRecord) est acceptable. Il suffit de faire un record d'une taille différence pour que ça ne compile plus
    Quel oeil !
    Avec ce simple record, le transtypage Pointer() ne fonctionne plus !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    type
      PMyRecord = ^TMyRecord;
      TMyRecord = record
        PropStr : String;
        PropInt: Integer;
      end;
    ça sent l'optimisation par Delphi non ?

    Bon, désolé d'avoir "Trollé" le sujet, je trouvais important que l'on sache quel est le niveau et la tolérance de ceux qui "juge" au niveau du Code, de sa clareté et maintenabilité, ... par expérience, j'ai souvent été critiqué pour mon utilisation des pointeurs au bureau ... alors j'ai préféré prendre les devants ... et c'est bien, on vient d'avoir une belle démonstration que peu de monde sait utiliser correctement les pointeurs ce qui n'est pas grave, ce n'est plus à la mode ...
    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

  10. #190
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Pour la fuite mémoire, effectivement, on a de la chance, Delphi est fort pour allouer au bon moment (comme la 1ere affectation semble-t-il)
    Heu... soyons sérieux. Delphi gère certes l'indirection des pointeurs automatiquement, mais il n'en est pas encore à faire les allocations/libération automatiquement (à par pour les string et les widestring). Tu fais allusion à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    var 
      MyRecord : TMyRecord; // Allocation d'un Record inutile
    Moi j'appelle ça une belle déclaration statique ! Il n'y a aucune allocation dynamique (sauf si on considère que la réservation de la variable sur la pile est une allocation).
    Il n'y a pas d'allocation dans ce cas, ni donc de free ou dispose à faire. C'est une simple variable en gestion automatique sur la pile.
    C'est tout l'intérêt de travailler avec un Record plutôt qu'un objet (remarque, je pense qu'on pourrait faire un objet de type Object au lieu de Class, ça doit fonctionner de la même manière (j'avoue que je n'ai pas utilisé les Object depuis Turbo Pascal 6)).

    ça sent l'optimisation par Delphi non ?
    Moi j'appellerai plutôt ça un bug ou une faiblesse au niveau des vérifications faites par le compilo.
    Lorsque j'ai vu le code de Félix Guillemot, je me suis demandé si ça avait un sens et comment ça pouvait marcher.
    Paul TOTH a répondu à la question ! Ca ne fonctionne pas, c'est juste un hasard si on n'a pas eu un Access Violation.

    ...on vient d'avoir une belle démonstration que peu de monde sait utiliser correctement les pointeurs ce qui n'est pas grave, ce n'est plus à la mode ...
    Et oui ! A force de se reposer sur les facilités du langage, on finit par oublier les bases

  11. #191
    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
    Effectivement, ce code étrange restera un mystère, perso, pour moi, ce débat sur les pointeurs est clos !

    J'ai fini mon Solveur ... pour les Grilles fournies en exemple :

    Méthode Basique : Elimine les Candidats pour chaque Ligne, Colonne, Bloc, ce qui résoud les grilles Faciles et Normales
    Méthode Profondre : Je n'utilise pas un vrai Brute Force (Attaque par Force Brute) comme FullSpeed, je tente toutes les combinaisons possibles crédibles dans avec une boucle For et une Boucle Récursive (et non 81 Boucle Imbriquée) ... bon ça me surprend vraiement que le Brute Force de FullSpeed soit si rapide (1/400s = 2.5ms) et que le mien soit si lent (1800ms ), ça doit venir de nos Speudo (ou du principe d'aléatoire que je n'ai pas tenté) ...

    P4 3Ghz
    1ere : Méthode Profonde : 430 ms
    2eme : Méthode Profonde : 44 ms
    3eme : Méthode Profonde : 9 ms
    4eme : Méthode Profonde : 1 860 ms (1.8s) (AI Escargot)
    5eme : Méthode Profonde : 12 360 ms (12.3s) (Easter Monster)
    1ère Grille 17 de FullSpeed : 12 minutes
    Dernière Grille 17 de FullSpeed : 25 minutes

    Bon, je vais bosser un peu sur la gueule du programme, et si j'ai le temps, ben faudrait que j'améliore ces temps ... ma méthode est terriblement simple (200 lignes) mais aussi pitoyablement lente, ... vos temps m'impressionne vraiement ... faut que je regarde cesméthode énumérées par Pascal Fonteneau ... j'avoue, je ne vois pas comment écrire le code pour ces méthodes ...
    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. #192
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    P4 3Ghz
    1ere : Méthode Profonde : 430 ms
    2eme : Méthode Profonde : 44 ms
    3eme : Méthode Profonde : 9 ms
    4eme : Méthode Profonde : 1 860 ms (1.8s) (AI Escargot)
    5eme : Méthode Profonde : 12 360 ms (12.3s) (Easter Monster)
    1ère Grille 17 de FullSpeed : 12 minutes
    Dernière Grille 17 de FullSpeed : 25 minutes

    Bon, je vais bosser un peu sur la gueule du programme, et si j'ai le temps, ben faudrait que j'améliore ces temps ... ma méthode est terriblement simple (200 lignes) mais aussi pitoyablement lente, ... vos temps m'impressionne vraiement ... faut que je regarde cesméthode énumérées par Pascal Fonteneau ... j'avoue, je ne vois pas comment écrire le code pour ces méthodes ...
    Effectivement, il y a un petit écart de perf avec nos solutions.
    C'est assez marrant d'ailleurs, parce que ma solution est également ridiculement simple (la partie résolution doit faire dans les 160 lignes, sur trois méthodes).

    Au fait, en relisant mon code récemment, je me suis rendu compte que les temps que j'ai donnés étaient ceux de la version non multi-threadée, et non pas avec le multi-threading (cette dernière ne marche pas aussi bien que je voudrais) !

  13. #193
    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
    Citation Envoyé par Franck SORIANO Voir le message
    ...sur trois méthodes ...
    Lol, ah des "vrais" méthodes ? Moi c'est mon approche perso de très mauvais joueur de sudoku ... j'ai même pas compris ces histoire de XYChain et autre machin du genre ... bon je sais que l'on peut donc faire un code court pour implémenter de "vrais" méthodes ... si je dépasse c'est que c'est foireux ...
    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

  14. #194
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Salut à tous,

    voici une version relativement stable que j'ai appelé Mini Sudoku codée en utilisant des fonctions de l'API windows uniquement (pour voir si j'en étais capable). Entre nous c'est plutôt galère. A défaut de rapidité au moins c'est un petit executable.

    Ctrl + C pour copier
    Ctrl + V pour coller
    Ctrl + R pour Résoudre
    Ctrl + E pour Effacer

    pour tous ces raccourcis, la fenêtre doit avoir le focus en cliquant gauche dessus (c'est galère mais bon je sais pas encore le faire autrement)

    Evidemment il est pas fini et il a des bugs connus comme par exemple il y a un 'c' lors du coller de la grille et je sais pas encore d'ou il vient :\
    Fichiers attachés Fichiers attachés
    Akim Merabet

  15. #195
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    P4 3Ghz
    1ere : Méthode Profonde : 430 ms
    2eme : Méthode Profonde : 44 ms
    3eme : Méthode Profonde : 9 ms
    4eme : Méthode Profonde : 1 860 ms (1.8s) (AI Escargot)
    5eme : Méthode Profonde : 12 360 ms (12.3s) (Easter Monster)
    1ère Grille 17 de FullSpeed : 12 minutes
    Dernière Grille 17 de FullSpeed : 25 minutes
    J'ai une question ? Qu'est ce que fait ton programme pendant tout ce temps ? des calculs ? Je ne comprends pas comment tu peux occuper autant de temps a calculer


    Citation Envoyé par ShaiLeTroll Voir le message
    ... ma méthode est terriblement simple (200 lignes) mais aussi pitoyablement lente, ... vos temps m'impressionne vraiement ... faut que je regarde cesméthode énumérées par Pascal Fonteneau ... j'avoue, je ne vois pas comment écrire le code pour ces méthodes ...
    Lol, niveau ligne, t'as géré ... enfin, c'est au détriment du temps Je suis plutot dans les 1500 lignes (enfin, pas de code "pur")
    Pour les méthodes que t'as cité, je n'en ai codé aucune, et je résoud quand meme pas mal de grilles ... Commence pas par ces méthodes, elles sont trop complexes !


    Citation Envoyé par Kaféine Voir le message
    pour tous ces raccourcis, la fenêtre doit avoir le focus en cliquant gauche dessus (c'est galère mais bon je sais pas encore le faire autrement)
    Tu pourrais par exemple mettre un Timer avec un temps assez court, et vérifier l'état des touches avec GetKeyState et GetAsyncKeyState. Vérifie que ta fenetre est au premier plan ...

  16. #196
    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
    Citation Envoyé par mick605 Voir le message
    J'ai une question ? Qu'est ce que fait ton programme pendant tout ce temps ? des calculs ? Je ne comprends pas comment tu peux occuper autant de temps a calculer ...
    Si je savais comment réduire le temps ...
    Pour une Grille 17, c'est presque 4^60 possiblité
    En fait il parcourt un arbre, et teste toutes les configurations de grilles possibles selon un ensemble de candidats, il ne va pas au bout si la grille est incohérente de base (controle colonne \ ligne), mais faut juste imaginer qu'il y a un nombre de possiblité effarante (ça compte en 5x10^30 pour Escargot AI) dont 99.99% sont fausses, il va générer presque 500 grilles (colonne et ligne OK) dont il va controller les Block (les carrés 3x3), et il continue jusqu'à ce qu'il trouve une grille dont les Blocks sont OK ...

    Citation Envoyé par mick605 Voir le message
    Lol, niveau ligne, t'as géré ... enfin, c'est au détriment du temps Je suis plutot dans les 1500 lignes (enfin, pas de code "pur")
    Pour les méthodes que t'as cité, je n'en ai codé aucune, et je résoud quand meme pas mal de grilles ... Commence pas par ces méthodes, elles sont trop complexes !
    Ben, j'ai fait la méthode bourrin, je suis un Troll !
    Sérieusement, comme je suis une quiche au Sudoku, je ne vois pas les idées d'algo évidentes qui peuvent exister ... mais je les trouverais ... je prévois de mettre un Algo pour réduire les Candidats avec de lancer la méthode Bourrin, mais c'est la que je sèche ... j'ai vu des méthodes sur les paires, les triples, les paires cachées, ... je comprends même pas la méthode de repérage ... ça vient du fait, que je n'ai du faire que 20 grilles faciles de ma vie ... je n'ai aucun réflexe de joueur ...

    Pour rigoler, voilà le code qui dure 21 minutes (je ne pense que pas que ce soit un code à modérer, il va pas aider grand monde ). Le Code pour créer AChain est plus long en fait ! un comble non ? l'initialisation des variables plus longue que le calcul lui-même

    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
     
      function RunChain(AChain: PSudokuSolverCellItemChain): Boolean;
      var
        I: Integer;
        D: Byte;
      begin
        Result := False;
     
        if Assigned(AChain) then
        begin
          with AChain^ do
          begin
            for I := Low(PackedDummies) to High(PackedDummies) do
            begin
              D := PackedDummies[I];
              if DummyLock(Col, Row, D) then
              begin
                try
                  FinalValue^ := D;
     
                  if RunChain(Next) then
                  begin
                    Result := True;
                    Exit;
                  end;
     
                  FinalValue^ := 0;
                finally
                  DummyUnLock(Col, Row, D);
                end;
              end;
            end;
          end;
        end
        else
        begin
          // Chaine Terminé donc c'est une Grille à Checker !
          Result := CheckBlock(True);
        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

  17. #197
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Ben, j'ai fait la méthode bourrin, je suis un Troll !
    Sérieusement, comme je suis une quiche au Sudoku, je ne vois pas les idées d'algo évidentes qui peuvent exister ... mais je les trouverais ...
    Tu pourrais faire (si cela ne l'ai pas déja fait) les paires, triplets cachés, et les candidats doubles, triples ... Rien qu'avec ca, t'en résoud pas mal !

  18. #198
    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
    "... les paires, triplets cachés, et les candidats doubles, triples, ... ",

    Tout à fait, je suis en train d'essayer de comprendre comme ça marche (c'est la mon problème pour le moment), je me suis imprimé quelque grille réduite par la Méthode Basique, et j'essaye de les résoudre à la main en suivant ces méthodes ...
    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

  19. #199
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Lol, ah des "vrais" méthodes ?
    Je parlais de méthodes au sens POO du terme (3 procédures ou fonctions si tu préfères), pas trois méthodes de résolution.

    Citation Envoyé par ShaiLeTroll Voir le message
    Pour rigoler, voilà le code qui dure 21 minutes (je ne pense que pas que ce soit un code à modérer, il va pas aider grand monde ).
    En effet, je n'y comprend déjà rien

    Juste une remarque : le with, il n'y a pas mieux pour rendre un code illisible !

    Puisque j'ai laché le morceau ici voici la façon dont j'ai multi-threadé ma solution :
    - J'ai plusieurs solveurs (le même en fait, mais paramétrés différemment) qui essaient chacun de résoudre la grille dans son coin à sa sauce.
    - Je prends le résultat du premier qui termine !
    - Le résultat est quand même assez moyen.

  20. #200
    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
    Tu es comme mon Chef, pas de with ... moi je trouve ça très utile, là de ce cas c'est super simple, toutes les variables qui suivent sont toutes des membres du AChain^, ça m'évite de répéter ...

    tient, code typique que j'ai tapé pour le Taf, il y a 2 heure :

    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
    begin
      with GridTestExamen.DataSource.DataSet do
      begin
        DisableControls();
        try
          First();
     
          while not EOF do
          begin
            Edit();
            FieldByName('Resultat').AsString := CalculResultatCancer(FieldByName('ExamID').AsInteger);
            Post();
     
            Next();
          end;
        finally
          EnableControls();
        end;
      end;
    end;
    Vous essayez tous de faire du Multi-Thread, moi avec mon P4, ça serait juste une catastrophe, car le calcul ce n'est que des opérations logiques ou mathématiques, il n'y a pas d'accès à des ressources lentes comme DD, Périphériques, ... du coup, windows, il va pas change vos threads de core sans arrêt, ... j'ai connu ça avec EasyPHP 1.8 et des Octo-Core, il passait plus de temps à lutter contre Windows pour le positionnement des threads qu'à exécuter la requête qui allait plus vite sur un mono-core, un comble non ?
    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

Discussions similaires

  1. Défi Migration de delphi 3 à delphi 8
    Par sitalebs dans le forum EDI
    Réponses: 8
    Dernier message: 03/01/2008, 14h30

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