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

C Discussion :

Créer des fonctions dynamiques


Sujet :

C

  1. #61
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    349
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 349
    Points : 376
    Points
    376
    Par défaut
    Superne0 a écrit:
    Est-ce que tu pourrais m'expliquer ton prog
    Je viens d'ajouter quelques commentaires explicatifs. L'idée est en gros de construire un tableau palier tel que:
    G(x)=y pour tout x de palier[y-1]+1 jusqu'à palier[y]

    Pour trouver la valeur de G(x), x étant donné, il faut donc trouver y tel que:
    palier[y-1]<x et palier[y]>=x. Dans ce cas, on a G(x)=y.
    Pour trouver cette valeur de y, on procède par dichotomie.

    La notation vmin += delta; est équivalente à vmin = vmin+delta;

    L'idée maintenant pour améliorer les performances, serait d'utiliser du hash-coding pour gérer la table des paliers. Si j'ai le temps, je vais essayer de m'y frotter ...

  2. #62
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 124
    Points : 53
    Points
    53
    Par défaut
    Citation Envoyé par josse95
    Je viens d'ajouter quelques commentaires explicatifs. L'idée est en gros de construire un tableau palier tel que:
    G(x)=y pour tout x de palier[y-1]+1 jusqu'à palier[y]

    Pour trouver la valeur de G(x), x étant donné, il faut donc trouver y tel que:
    palier[y-1]<x et palier[y]>=x. Dans ce cas, on a G(x)=y.
    Pour trouver cette valeur de y, on procède par dichotomie.

    La notation vmin += delta; est équivalente à vmin = vmin+delta;

    L'idée maintenant pour améliorer les performances, serait d'utiliser du hash-coding pour gérer la table des paliers. Si j'ai le temps, je vais essayer de m'y frotter ...
    OK, merci.
    En fait, c'est surtout la notation apparamment très souvent utilisée, que je ne conaissait pas, qui me bloquait.
    Je m'étais tellement focalisé sur la récursivité, que j'en ai oublié la dichotomie, c'est aussi une bonne solution.
    En tout cas, merci à tous pour votre aide ...

  3. #63
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Voilà le code de josse mais en C
    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
     
    #include <stdio.h>
    #include <time.h>
    #include <malloc.h>
    #include <stdlib.h>
     
    unsigned int *palier;
    unsigned int maxpalier=1,maxval=1;
     
    unsigned long g(unsigned int n)
    {
        unsigned int max,i,v,vmin,vmax,delta;
     
        if (n<=1) return 1;
     
        /* cas n<=maxval. On a déjà calculé G(n) */
        /* recherche donc (par dichotomie) dans palier la valeur
         * correspondante */
        if (maxval>=n)
        {
            for (vmin=1,vmax=maxpalier;;)
            {
                delta = (vmax-vmin)>>1;
                if (delta<=0) break;
                if (palier[vmax-delta]<n)
                {
                    vmin += delta;
                }
                else
                {
                    vmax -= delta;
                }
            }
            return(vmax);
        }
     
        palier[0] = 0;
        palier[1] = 1;
        palier[2] = 2;
     
        /* calcule maintenant G(x)  pour x=(maxval+1) jusqu'a n */
        /* les valeurs de 2 jusqu'a maxval ont deja ete calculees */
        /* et figurent dans le tableau palier */
     
        for (i=maxval+1,max=maxpalier;i<=n;i++)
        {
            /* a ce niveau, on a G(i-1)=max */
            /* calcule ensuite G(G(i-1))=G(max) en recherchant par */
            /* dichotomie a quel palier correspond max */
            for (vmin=1,vmax=max;;)
            {
                delta = (vmax-vmin)>>1;
                if (delta<=0) break;
                if (palier[vmax-delta]<max)
                {
                    vmin += delta;
                }
                else
                {
                    vmax -= delta;
                }
            }
            /* en sortie du for, on a G(G(i-1))=vmax */
            v = i - vmax;
            /* calcule maintenant G(i-G(G(i-1))) toujours en recherchant */
            /* dans palier par dichotomie */
            for (vmin=1,vmax=max;;)
            {
                delta = (vmax-vmin)>>1;
                if (delta<=0) break;
                if (palier[vmax-delta]<v)
                {
                    vmin += delta;
                }
                else
                {
                    vmax -= delta;
                }
            }
            /* en sortie de la boucle for, on a G(i-G(G(i-1)))=vmax */
            /* maintenant, on met a jour le tableau des paliers */
            if (vmax+1>max)
            {
                /* nouveau palier */
                max = vmax+1;
            }
            /* on a G(x)=max pour x=palier[max-1]+1 jusqu'a i */
            palier[max] = i;
        }
        /* memorise la valeur maxval la plus haute pour laquelle on a calcule G */
        /* ainsi que maxpalier=G(maxval) */
        if (n>maxval)
        {
            maxval = n;
            maxpalier = max;
        }
        return max;
    }
     
    int main()
    {
        unsigned long v;
        char buf[32],*endptr;
     
        palier = malloc(10000000*sizeof(*palier));
     
        if(palier == NULL) {
            return EXIT_FAILURE;
        }
     
        palier[0] = 0;
        palier[1] = 1;
        maxpalier = 1;
     
        while (1)
        {
            if(fgets(buf,sizeof(buf),stdin)==NULL) {
                break;
            }
     
            v = strtol(buf, &endptr, 0);
            if(*endptr != '\n') {
                break;
            }
     
            v = g(v);
            printf("%lu\n", v);
        }
        free(palier);
        return EXIT_SUCCESS;
    }
    Par contre, il est trop lent... Pour le calcul de 100 millions par exemple prend 9 secondes...

    Ma version donne le résultat en instantané...

    Mais les deux versions ne sont pas acceptables. Ma version utilise trop de mémoire et celle de josse est trop lente pour les grands nombres...

    Jc

  4. #64
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Ceci semble fonctionner:
    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
     
    #define VALRANGE_SIZE 1000000
     
     
    int g_rec(int n)
     {
     if (n==1) return 1;
     else return 1+g_rec(n-g_rec(g_rec(n-1)));
     }
     
     
    int g(int n) /*Non récursive*/
     {
     static int valrange[VALRANGE_SIZE];
     int mem,index;
     
     if (n==1) return 1;
     valrange[2]=3;
     index=2;
     mem=2;
     while (valrange[index]<n)
      {
      ++index;
      if (index>valrange[mem]) ++mem;
      valrange[index]=valrange[index-1]+mem;
      }
     return index;
     }
     
     
    int main(int argc,char **argv)
     {
     int startn,endn,res,i;
     DWORD starttime,endtime;
    #ifdef BOTH
     int res_rec;
    #endif
     
     if (argc<2) return -1;
     startn=atoi(argv[1]);
     if (argc>2) endn=atoi(argv[2]);
     else endn=startn;
     for (i=startn;i<=endn;++i)
      {
      starttime=GetTickCount();
    #ifdef RECURSIVE
      res=g_rec(i);
    #else
      res=g(i);
    #endif
    #ifdef BOTH
      res_rec=g_rec(i);
    #endif
      endtime=GetTickCount();
    #ifdef BOTH
      printf("g_rec(%9d)=%d\t",i,res_rec);
    #endif
      printf("g(%9d)=%d\n",i,res);
      }
     if (argc==2)
      printf("Time elapsed: %.3f s",(double) (endtime-starttime)/1000.0);
     return 0;
     }

  5. #65
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    Ceci semble fonctionner:
    Ca a l'air déjà nettement mieux en effet. Tu traites 1 millions de nombres aléatoires en 20 secondes.

    Je le fais plus vite mais j'ai déjà fait tout le travail avec mon tableau

    Ca me semble pas mal du tout .

    Je pense que tu pourrais gagner si tu ne chercher pas à chaque fois au début de ta table mais en faisant une recherche dichotomique dedans.

    Jc

  6. #66
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Ca a l'air déjà nettement mieux en effet. Tu traites 1 millions de nombres aléatoires en 20 secondes.
    Non, mon programme calcule pour n=1 milliard en 16 ms.

  7. #67
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    Non, mon programme calcule pour n=1 milliard en 16 ms.
    Non, tu n'as pas compris ce que je disais. J'ai modifié ton programme pour qu'il prenne en entrée un fichier avec un millions de nombres aléatoires.

    Le temps de tout traiter est de 20 secondes pour ton programme.

    Jc

  8. #68
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Non, tu n'as pas compris ce que je disais. J'ai modifié ton programme pour qu'il prenne en entrée un fichier avec un millions de nombres aléatoires.

    Le temps de tout traiter est de 20 secondes pour ton programme.

    Jc
    OK, mais comme cela, vous prenez en compte le temps des entrées-sorties qui rallongent considérablement. Si vous regardez ma fonction, vous verrez qu'elle calcule pour tous les nombres jusqu'à n passé en paramètre.

  9. #69
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    OK, mais comme cela, vous prenez en compte le temps des entrées-sorties qui rallongent considérablement. Si vous regardez ma fonction, vous verrez qu'elle calcule pour tous les nombres jusqu'à n passé en paramètre.
    Tu as une fonction d'entrée g et moi aussi Du coup, la seule différence c'est notre facon de faire le calcul.

    De toute facon, je considère ta solution meilleure que la mienne dans le sens où on n'a pas besoin de beaucoup de mémoire pour avoir des bonnes performances.

    Je pense par contre, qu'une recherche dichotomique serait bénéfique, comme cela tu conserverais les calculs que tu as déjà fait...
    Jc

  10. #70
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Je pense par contre, qu'une recherche dichotomique serait bénéfique, comme cela tu conserverais les calculs que tu as déjà fait...
    Jc
    Pourquoi? Je n'effectue aucune recherche dans mon algorithme. Je ne saisis pas ce que vous voulez dire.

  11. #71
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    Pourquoi? Je n'effectue aucune recherche dans mon algorithme. Je ne saisis pas ce que vous voulez dire.
    Justement, à chaque appel, tu recommences ton calcul à partir de 0. Ce serait meilleur de se souvenir des valeurs calculées précédemment...

    Jc

  12. #72
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Justement, à chaque appel, tu recommences ton calcul à partir de 0. Ce serait meilleur de se souvenir des valeurs calculées précédemment...

    Jc
    Le programme s'en souvient. Essayez avec ce code-ci. La syntaxe de l'appel est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g.exe BORNE_INF BORNE_SUP
    (Je l'ai tapé un peu vite, alors j'espère qu'il n'y a pas d'erreur...)
    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
     
    #define VALRANGE_SIZE 1000000
     
     
    static int valrange[VALRANGE_SIZE];
     
     
    int g_rec(int n)
     {
     if (n==1) return 1;
     else return 1+g_rec(n-g_rec(g_rec(n-1)));
     }
     
     
    int g(int n) /*Non récursive*/
     {
     int mem,index;
     
     if (n==1) return 1;
     valrange[1]=1;
     valrange[2]=3;
     index=2;
     mem=2;
     while (valrange[index]<n)
      {
      ++index;
      if (index>valrange[mem]) ++mem;
      valrange[index]=valrange[index-1]+mem;
      }
     return index;
     }
     
     
    int g2(int n,int firstindex)
     {
     int i;
     
     for (i=firstindex;valrange[i]<n;++i);
     return i;
     }
     
     
    int main(int argc,char **argv)
     {
     int startn,endn,res,i,maxval;
     DWORD starttime,endtime;
     
     if (argc<2) return -1;
     startn=atoi(argv[1]);
     if (argc>2) endn=atoi(argv[2]);
     else endn=startn;
     starttime=GetTickCount();
     maxval=g(endn);
     res=1;
     for (i=startn;i<=endn;++i)
      {
      /*res=g2(i,res);*/
      for (;valrange[res]<i;++res);
    #ifdef DISPLAY
      printf("g(%9d)=%d\n",i,res);
    #endif
      }
     endtime=GetTickCount();
     printf("Time elapsed: %.3f s",(double) (endtime-starttime)/1000.0);
     return 0;
     }

  13. #73
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    349
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 349
    Points : 376
    Points
    376
    Par défaut
    Si j'ai bien compris ton code fearyourself, il est basé sur le préchargement en mémoire d'un tableau calculé dans une première passe.

    Les temps que tu annonce sont les temps de recherche dans ce tableau. Je pense qu'ils ne sont pas corrects dans la mesure où tu devrais prendre en compte le temps de constitution du tableau.
    Ceci est similaire à mon code où si tu appelles deux fois de suite la même valeur, la réponse est instantanée pour le deuxième appel (mais je le répète, c'est de la triche !).

    Le code de stephl est lui basé sur le fait qu'il a reussi à déterminer la longueur de chaque palier (détrompe moi si ce n'est pas le cas). Il ne se sert donc pas de la formule 1+G(n-G(G(n-1))) pour remplir le tableau des paliers mais le construit d'une manière beaucoup plus rapide. C'est effectivement la meilleure solution et je ne pense pas que l'on puisse faire beaucoup mieux.

  14. #74
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Cela ne fonctionnerait pas non plus à mon avis, du moins pas assez bien. J'aurais proposé ceci plutôt :

    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    #define VALRANGE_SIZE 1000000
     
    int g(int n) /*Non récursive*/
    {
        static int valrange[VALRANGE_SIZE] = {0,1,3};
        static int mem=2,index=2;
        int min,mid,max;
     
        if (n==1) {
            return 1;
        }
     
        if(valrange[index] < n) {
            /* On doit calculer */
            while (valrange[index]<n)
            {
                ++index;
                if (index>valrange[mem]) ++mem;
                valrange[index]=valrange[index-1]+mem;
            }
            return index;
        }
        else {
            /* Est-ce le dernier element */
            if( (valrange[index]>=n) && (valrange[index-1]<n) ) {
                return index;
            }
     
            /* Sinon on cherche */
            min = 1;
            max = index;
            mid = (max+min) / 2;
     
     
            do {
                if((valrange[mid-1]<n)&&(valrange[mid]>=n)) {
                    return mid;
                }
     
                if(valrange[mid] < n) {
                    min = mid;
                }
                else {
                    max = mid;
                }
                mid = (max+min)/2;
     
            }while(min != max);
     
            fprintf(stderr, "Error\n");
            exit(EXIT_FAILURE);
        }
    }
     
     
    int main(int argc,char **argv)
    {
        int v,res;
        char buf[128], *endptr;
     
     
        while(1)
        {
            if(fgets(buf,sizeof(buf),stdin)==NULL) {
                break;
            }
     
            v = strtol(buf, &endptr, 0);
            if(*endptr != '\n') {
                break;
            }
            res=g(v);
            printf("%d\n",res);
        }
        return 0;
    }
    Qui est nettement plus rapide que ton code de départ et permet de traiter 4.5 millions d'éléments en 8s par rapport à mon code qui le fait 9s

    Je pense qu'on a une solution acceptable maintenant

    Jc

  15. #75
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par josse95
    Le code de stephl est lui basé sur le fait qu'il a reussi à déterminer la longueur de chaque palier (détrompe moi si ce n'est pas le cas). Il ne se sert donc pas de la formule 1+G(n-G(G(n-1))) pour remplir le tableau des paliers
    C'est cela!
    En fait, la formule de la suite ne m'a pas aidé (au contraire). Avec le lien qui a été fourni (http://acm.uva.es/p/v100/10049.html), on se rend compte que le tableau des paliers est assez aisément rempli à la main. Après, il ne reste plus qu'à traduire cela en C.

  16. #76
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par josse95
    Si j'ai bien compris ton code fearyourself, il est basé sur le préchargement en mémoire d'un tableau calculé dans une première passe.

    Les temps que tu annonce sont les temps de recherche dans ce tableau. Je pense qu'ils ne sont pas corrects dans la mesure où tu devrais prendre en compte le temps de constitution du tableau.
    Ceci est similaire à mon code où si tu appelles deux fois de suite la même valeur, la réponse est instantanée pour le deuxième appel (mais je le répète, c'est de la triche !).

    Le code de stephl est lui basé sur le fait qu'il a reussi à déterminer la longueur de chaque palier (détrompe moi si ce n'est pas le cas). Il ne se sert donc pas de la formule 1+G(n-G(G(n-1))) pour remplir le tableau des paliers mais le construit d'une manière beaucoup plus rapide. C'est effectivement la meilleure solution et je ne pense pas que l'on puisse faire beaucoup mieux.
    La question est de résoudre la formule 1+G(n-G(G(n-1))) le plus rapidement possible. D'ailleurs cette formule n'apparait pas de le problème de base, je me demande d'où c'est venu.

    Il n'y a pas de triche dans le sens où rien ne nous interdit de faire un précalcul avant. L'algorithme fonctionne ensuite comme une recherche en effet. Ensuite, la solution de stephl est meilleure dans le sens où le calcul est aussi rapide et l'utilisation mémoire est aussi très faible par rapport à ma solution.

    Jc

    Jc

  17. #77
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Qui est nettement plus rapide que ton code de départ et permet de traiter 4.5 millions d'éléments en 8s par rapport à mon code qui le fait 9s
    Pourquoi diable effectuez-vous une recherche par dichotomie? Avec ce code-ci qui comprend l'écriture des paliers dans un fichier (le temps des E/S est comptabilisé), on calcule 1 milliard d'éléments en 6 à 7 secondes (le temps de calcul pur sans E/S est de 2 à 3 s).
    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
     
    #define VALRANGE_SIZE 1000000
     
     
    static int valrange[VALRANGE_SIZE];
     
     
    int g_rec(int n)
     {
     if (n==1) return 1;
     else return 1+g_rec(n-g_rec(g_rec(n-1)));
     }
     
     
    int g(int n) /*Non récursive*/
     {
     int mem,index;
     
     if (n==1) return 1;
     valrange[1]=1;
     valrange[2]=3;
     index=2;
     mem=2;
     while (valrange[index]<n)
      {
      ++index;
      if (index>valrange[mem]) ++mem;
      valrange[index]=valrange[index-1]+mem;
      }
     return index;
     }
     
     
    int g2(int n,int firstindex)
     {
     int i;
     
     for (i=firstindex;valrange[i]<n;++i);
     return i;
     }
     
     
    int main(int argc,char **argv)
     {
     int startn,endn,res,i,maxval;
     DWORD starttime,endtime;
    #ifdef TOFILE
     FILE *f;
    #endif
     
     if (argc<2) return -1;
     startn=atoi(argv[1]);
     if (argc>2) endn=atoi(argv[2]);
     else endn=startn;
     starttime=GetTickCount();
     maxval=g(endn);
     res=1;
     for (i=startn;i<=endn;++i)
      {
      /*res=g2(i,res);*/
      for (;valrange[res]<i;++res);
    #ifdef DISPLAY
      printf("g(%9d)=%d\n",i,res);
    #endif
      }
    #ifdef TOFILE
     f=fopen("out.txt","w");
     for (i=1;i<=maxval;++i)
      fprintf(f,"g(%9d)=%d\n",valrange[i],i);
     fclose(f);
    #endif
     endtime=GetTickCount();
     printf("Time elapsed: %.3f s",(double) (endtime-starttime)/1000.0);
     return 0;
     }

  18. #78
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    Pourquoi diable effectuez-vous une recherche par dichotomie? Avec ce code-ci qui comprend l'écriture des paliers dans un fichier (le temps des E/S est comptabilisé), on calcule 1 milliard d'éléments en 6 à 7 secondes (le temps de calcul pur sans E/S est de 2 à 3 s).
    C'est faux. Tu calcules de 1 à 1 milliard séquentiellement. Je teste sur un code qui prend 4 millions de nombres aléatoires...

    Qu'est-ce que tu ne comprends pas sur ce principe ?

    Jc

  19. #79
    Membre éclairé Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Points : 771
    Points
    771
    Par défaut
    Citation Envoyé par fearyourself
    Je teste sur un code qui prend 4 millions de nombres aléatoires...
    OK, là je comprends mieux les temps que vous donnez.
    En fait, ce que je ne suis pas sûr d'avoir saisi, c'est la limite de temps (10 s). Cela correspond-t-il au calcul de g(n) pour un n donné quel qu'il soit, ou bien au calcul de p valeurs de g(n), n étant choisi aléatoirement p fois. Dans le second cas, avec nos méthodes actuelles, cela s'apparente plus à un algorithme de recherche qu'autre chose.

  20. #80
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par stephl
    OK, là je comprends mieux les temps que vous donnez.
    En fait, ce que je ne suis pas sûr d'avoir saisi, c'est la limite de temps (10 s). Cela correspond-t-il au calcul de g(n) pour un n donné quel qu'il soit, ou bien au calcul de p valeurs de g(n), n étant choisi aléatoirement p fois. Dans le second cas, avec nos méthodes actuelles, cela s'apparente plus à un algorithme de recherche qu'autre chose.
    C'est le deuxième cas en effet.

    10 secondes correspond au temps maximal pour
    le calcul de p valeurs de g(n), n étant choisi aléatoirement p fois.
    Une solution serait de faire ce que tu voulais faire, calculer la plus grande valeur et après simplement faire de la recherche.

    Les modifications que j'ai faites font qu'on ne poursuit que le calcul si nécessaire, basculant sur une recherche dichotomique si on a déjà le résultat dans la table.

    Ceci n'enlève en rien que ton code est bon et fonctionne à merveille

    Jc

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

Discussions similaires

  1. Procédure Stockée pour créer des TABLE dynamiquement
    Par GuyverZ dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 12/05/2009, 22h29
  2. Réponses: 3
    Dernier message: 22/01/2009, 21h05
  3. Réponses: 2
    Dernier message: 14/07/2006, 14h24
  4. Créer des fonctions de conversion d'unités
    Par frenzy dans le forum Langage
    Réponses: 6
    Dernier message: 01/03/2006, 09h52
  5. Créer des fonctions au sein d'un script
    Par mat.M dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 31/03/2004, 15h25

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