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

Algorithmes et structures de données Discussion :

Recherche de nombres premiers satisfaisant certains critères


Sujet :

Algorithmes et structures de données

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 11
    Par défaut Recherche de nombres premiers satisfaisant certains critères
    Bonjour,

    J'ai un problème de recherche de nombres premiers, mais je me heurte à de gros problèmes d'optimisation : mon code (en python, mais ça n'a pas d'importance) ne pourra pas résoudre le problème avant au mieux quelques années.
    Si quelqu'un peut me donner un coup de main sur la façon d'optimiser ça, mathématiquement et/ou algorithmiquement, ce serait vraiment sympa.

    Problème :
    Le trio de nombres premiers (3, 37, 67) possède une propriété intéressante. Si on concatène deux de ses nombres, on obtient toujours un nombre premier (337, 367, 373, 673, 3767, 6737 sont tous premiers).
    Le quadruplet (3, 7, 109, 673) possède également cette propriété.

    Intéressons-nous aux quintuplets la possédant. Plus particulièrement au quintuplet (p1, p2, p3, p4, p5) défini ainsi :

    p1, p2, p3, p4 et p5 sont des nombres premiers
    p1 < p2 < p3 < p4 < p5
    Si on concatène deux nombres du quintuplet, on obtient toujours un nombre premier
    La somme S=p1+p2+p3+p4+p5 est la plus petite possible qui soit supérieure à 100 000

    J'ai la liste des nombres premiers de 2 à 100k, car j'ai supposé que la solution comprenait probablement uniquement des nombres inférieurs à 100k, mais c'est une pure supposition.
    J'ai la liste des nombres premiers de 2 à 1 milliard
    Et je l'ai également triée par longueur (donc tous les nombres premiers inférieurs à 10, de 10 à 99, de 100 à 999, etc...

    Merci d'avance

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 295
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 295
    Par défaut
    Bonjour

    • Tu expliques une situation, mais pas un problème. On ne sait pas ce que tu veux faire.
    • Tu demandes une optimisation mais tu n'as rien fait. Donc, rien n'est à optimiser.


    Et puis, même la situation n'est pas super bien décrite. Le triplet (3;3;7) est-il un triplet de départ acceptable ? Autrement dit, peut-on répéter les nombres ?

  3. #3
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Autrement dit, peut-on répéter les nombres ?
    À priori, je dirais non puisque p1 < p2 < p3 < p4 < p5.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 11
    Par défaut
    Pour l'instant, j'ai la liste des nombres premiers, de 2 à 100 000, et de 100 000 à 1 milliard, et j'ai 5 boucles imbriquées
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    pour 0 de 1 à n - 5
      pour j de i + 1 à n - 4
        si concat(p[i], p[j]) est dans p et si concat(p[j], p[i] est dans p alors
          pour k de j + 1 à n - 3
            si concat(p[i], p[k]) est dans p et si concat(p[k], p[i] est dans p et si concat(p[k], p[j] est dans p et si concat(p[j], p[k] est dans p alors
              ...
              // Et on continue sur 5 niveaux
    mais c'est inefficace.
    J'ai essayé de construire une liste de tous les premiers dont la concaténation est aussi un entier, mais c'est aussi extrêmement long.

    NB : Si la concaténation de 2 premiers est plus grande que le max du tableau des premiers (1 milliard), on fait un test de primalité en utilisant le tableau en question pour les diviseurs potentiels.

  5. #5
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 656
    Par défaut
    Bonjour CosmoKnacki,
    Citation Envoyé par CosmoKnacki Voir le message
    À priori, je dirais non puisque p1 < p2 < p3 < p4 < p5.
    Il y a une autre raison, ces nombres seraient de la forme 10np+p (n étant le nombre de chiffres de p). nous aurions donc comme résultat un nombre multiple de 10n+1 donc non premier. Il n'y a que le cas de p = 1 qui marcherais, mais p=1 est lui même exclu des premiers.

    Salut.

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Bien vu, effectivement, la concatenation d'un même nombre est forcément multiple de 11, 101, 1001... Sauf pour 1 qui n'est pas premier de toute façon.

    À noter que pour ce qui nous occupe, on peut d'emblée retirer 2 et 5 de la liste.

  7. #7
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 656
    Par défaut
    Bonjour,

    Je crois que j'aurais tendance à prendre le problème à l'envers.

    Je partirais des plus grands de la liste pour aller vers les plus petits.

    1. Balayage descendant. Pour chaque n j'estimerais la puissance de 10 correspondante, la diviserais par 2 et arrondirais le résultat à l'entier supérieur t, pour pouvoir calculer d = 10t
    2. Div/mod d me donnent alors deux nombres qui doivent être premiers pour ce sujet.
    3. Si c'est le cas, alimenter deux entrée dans une liste (triée). Pour chaque entrée, augmenter cmpt + 1, noter son index premier propre et ajouter à sa propre liste secondaire d'index de premiers celui qui est associé.
    4. Réitérer en prenant d = 10*d jusqu'à d >= n. Revenir en 2
    5. Passer au n inférieur. Revenir en 1
    6. Nettoyage. Ensuite, pour des couples parmi 5, supprimer toutes les entrées de la liste dont le compteur cmpt est inférieur à 4.
    7. Diminuer le compteur de toutes les entrées de la liste secondaire dont un des index de premier ne correspond pas à une entrée de la liste principale et la retirer de cette liste secondaire. S'il y a au moins une diminution, revenir en 6

    A la fin nous avons une liste réduite (voire vide) d'entrées qui sont toutes associées à au moins 4 autres. Il faut vérifier que les sous listes (augmentées de l'index propre à l'entrée) se recoupent et que le recoupement est bien d'au moins 5 (si plus il y a des combinatoires dans l'air).

    L'idée est d'utiliser l'appauvrissement naturel. Le découpage d'un premier en deux nombres sera invalide dès que l'un d'eux sera non premier ce qui sera très fréquent. On devrait être, au doigt mouillé, en O(nlog(n)).
    Comme beaucoup d'algorithmes qui cherchent à gagner du temps, celui-ci est assez gourmand en espace mémoire.

    C'est une idée non testée qui mérite certainement des aménagements et correctifs.

    Salutations

  8. #8
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 295
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 295
    Par défaut
    Bravo pour vos réponses brillantes.

    Ici, je n'ai qu'un fichier avec les nombres premiers jusqu'à un million. J'ai considéré qu'un n-uplet était un (n-1)-uplet auquel on rajoutait un élément. On va donc déterminer les couples de nombres premiers qui s'acceptent, puis on va successivement agrandir le n-uplet. Comment ? En calculant un score. On ajoute 1 si le nombre est toléré par un nombre existant déjà dans le n-uplet. Exemple : Si un nombre atteint un score de 3 à partir d'un triplet c'est que ce nombre est compatible avec tous les autres. On peut donc créer un quadruplet.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ./uplet.awk prems.txt >couples.txt
     
    ./agrandir_uplet.awk couples.txt couples.txt >triplets.txt
    echo "----- triplets -----"
    cat triplets.txt
    ./agrandir_uplet.awk couples.txt triplets.txt >quadruplets.txt
    echo "----- quadruplets -----"
    cat quadruplets.txt
    ./agrandir_uplet.awk couples.txt quadruplets.txt >quintuplets.txt
    echo "----- quintuplets -----"
    cat quintuplets.txt
    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
    #!//usr/bin/awk -f
     
    {
            p[NR]=$1;
            v[$1]++;
    }
     
    END{
            for (i=1;i<=NR;i++)
            {
                    #print "----",i,p[i],"-----"
                    for (j=i+1;j<=NR;j++)
                            if (length(""p[i]""p[j])<7)
                            {
                                    if ((v[p[i]""p[j]]!="")&&(v[p[j]""p[i]]!=""))
                                            print p[i],p[j];
                            }
                            else
                                    break;
            }
    }
    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
    #!/usr/bin/awk -f
     
    (FNR==NR){
            q[$1]++;
            c[$1,q[$1]]=$2;
            next;
    }
     
    {
            delete score;
            for (r=1;r<=NF;r++)
                    for (i=1;i<=q[$r];i++)
                            score[c[$r,i]]++;
            for (m in score)
                    if (score[m]==NF)
                            print $0,m;
    }
    Et la fin de la sortie :
    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
    631 739 751
    661 877 883
    683 719 911
    709 823 967
    719 911 947
    733 883 991
    809 821 827
    809 929 983
    821 827 857
    ----- quadruplets -----
    3 7 109 673
    3 37 67 5923
    3 37 67 2377
    7 19 97 4507
    7 19 97 3727
    23 311 677 827
    ----- quintuplets -----
    Il ne trouve pas de quintuplet. Ce n'est pas étonnant car la plus grosse concaténation ne peut pas dépasser 6 chiffres.
    Pour information, le temps total d'exécution du programme ne dépasse pas 2 secondes.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Février 2004
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 11
    Par défaut
    Flodelarab :
    La solution avec awk explose en temps quand on augmente la taille du fichier. Il y a peut-être moyen de calmer le phénomène en splittant le fichier en plusieurs morceaux, je vais essayer.

    Guesset :
    Ta solution a l'air intéressante, surtout si elle permet d'éviter les boucles imbriquées. Pourrais-tu réexpliquer ton algo ? Notamment la partie concernant la division avec le modulo. Merci.

  10. #10
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Bonjour,

    Mon gribouillage sans prétentions. C'est mal testé, car c'est un peu chiant à vérifier.
    C'est pas commenté, je l'ai écrit au hasard, mais j'ai laissé le débug.
    Et comme je suis très mauvais en math, il y a très probablement des évidences qui m'échappent.

    Mais bon, si ça te donnes des pistes, tant mieux, ce sera toujours mieux que rien,
    ce programme est parti pour pourrir dans mon dd.

    Le cache des nombres premiers nécessite 16giga de ram (.... ça se calme à 8g après un scavenge du GC),
    à changer dans l'init au besoin.

    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
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
     
    package main
     
    import (
    	"fmt"
    	"sort"
    	"strconv"
    	"sync"
    	"time"
     
    	"github.com/fxtlabs/primes"
    	"github.com/pkg/profile"
    	"gonum.org/v1/gonum/stat/combin"
    )
     
    func main() {
    	defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
     
    	st := time.Now()
    	defer func() {
    		fmt.Println(time.Since(st))
    	}()
     
    	ps := primes.Sieve(100_000)
     
    	combin_primes_mt(ps, 4, func(i []int) {
    		fmt.Printf("  => %v\n", print_primes(ps, i))
    		// fmt.Printf("     %v\n", print_concat_primes(ps, i))
    		// if !check_primes(ps, i) {
    		// 	os.Exit(1)
    		// }
    	})
    	return
    	// combin_primes_start(ps, len(ps)-4, 4, func(i []int) {
    	// 	fmt.Printf("  => %v\n", print_primes(ps, i))
    	// 	// fmt.Printf("     %v\n", print_concat_primes(ps, i))
    	// 	// if !check_primes(ps, i) {
    	// 	// 	os.Exit(1)
    	// 	// }
    	// })
     
    	// return
     
    	combin_primes(ps, 4, func(i []int) {
    		fmt.Printf("  => %v\n", print_primes(ps, i))
    		// fmt.Printf("     %v\n", print_concat_primes(ps, i))
    		// if !check_primes(ps, i) {
    		// 	os.Exit(1)
    		// }
    	})
    }
     
    const debug = !true
     
    func combin_primes(ps []int, k int, cb func([]int)) {
    	n := len(ps)
    	if debug {
    		fmt.Println("n", n)
    		fmt.Println("k", k)
    	}
    	dst := make([]int, k)
    	for i := range dst {
    		dst[i] = i
    	}
    	l := k - 1
    	c := 1
    	if debug {
    		fmt.Println()
    		fmt.Printf("c1=%v dst=%v primes=%v\n",
    			c, dst, print_primes(ps, dst))
    	}
    	for dst[0] < n-k {
    		if debug {
    			<-time.After(time.Second / 2)
    		}
    		var ok bool
    		for dst[c] < n-(k-c) {
    			if valid_primes_pairs(ps, dst[:c], dst[c]) {
    				ok = true
    				break
    			}
    			dst[c]++
    		}
    		if debug {
    			fmt.Printf("c2=%v dst=%v primes=%v\n",
    				c, dst, print_primes(ps, dst))
    		}
    		if c == l && dst[c] < n-(k-c) {
    			if ok || valid_primes_pairs(ps, dst[:c], dst[c]) {
    				cb(dst)
    				dst[c]++
    				continue
    			}
    		}
    		if !ok {
    			dst[c-1]++
    			dst[c] = dst[c-1] + 1
    			c--
    			if debug {
    				fmt.Printf("c3=%v dst=%v primes=%v\n",
    					c, dst, print_primes(ps, dst))
    			}
    			continue
    		}
    		c++
    		if c > l {
    			c = 1
    			dst[c]++
    			continue
    		}
    		for i := c; i < k; i++ {
    			dst[i] = dst[i-1] + 1
    		}
    		if debug {
    			fmt.Printf("c4=%v dst=%v primes=%v\n",
    				c, dst, print_primes(ps, dst))
    		}
    	}
    }
     
    func combin_primes_mt(ps []int, k int, cb func([]int)) {
     
    	lmt := make(chan struct{}, 8)
    	c := make(chan []int, 10)
    	var wg sync.WaitGroup
    	wg.Add(1)
    	go func() {
    		defer wg.Done()
    		for i := 0; i < len(ps)-k; i++ {
    			wg.Add(1)
    			i := i
    			lmt <- struct{}{}
    			go func() {
    				defer wg.Done()
    				combin_primes_start(ps, i, k, func(r []int) {
    					c <- r
    				})
    				<-lmt
    			}()
    		}
    	}()
    	go func() {
    		wg.Wait()
    		close(c)
    	}()
    	for o := range c {
    		cb(o)
    	}
    }
     
    func combin_primes_start(ps []int, st, k int, cb func([]int)) {
    	n := len(ps)
    	if debug {
    		fmt.Println("n", n)
    		fmt.Println("k", k)
    	}
    	if st > n-k {
    		return
    	}
    	dst := make([]int, k)
    	for i := range dst {
    		dst[i] = st + i
    	}
    	l := k - 1
    	c := 1
    	if debug {
    		fmt.Println()
    		fmt.Printf("c1=%v dst=%v primes=%v\n",
    			c, dst, print_primes(ps, dst))
    	}
    	for dst[0] < n-k {
    		if debug {
    			<-time.After(time.Second / 2)
    		}
    		var ok bool
    		for dst[c] < n-(k-c) {
    			if valid_primes_pairs(ps, dst[:c], dst[c]) {
    				ok = true
    				break
    			}
    			dst[c]++
    		}
    		if debug {
    			fmt.Printf("c2=%v dst=%v primes=%v\n",
    				c, dst, print_primes(ps, dst))
    		}
    		if c == l && dst[c] < n-(k-c) {
    			if ok || valid_primes_pairs(ps, dst[:c], dst[c]) {
    				cb(dst)
    				dst[c]++
    				continue
    			}
    		}
    		if !ok {
    			dst[c-1]++
    			dst[c] = dst[c-1] + 1
    			c--
    			if c == 0 {
    				return
    			}
    			if debug {
    				fmt.Printf("c3=%v dst=%v primes=%v\n",
    					c, dst, print_primes(ps, dst))
    			}
    			continue
    		}
    		c++
    		if c > l {
    			c = 1
    			dst[c]++
    			continue
    		}
    		for i := c; i < k; i++ {
    			dst[i] = dst[i-1] + 1
    		}
    		if debug {
    			fmt.Printf("c4=%v dst=%v primes=%v\n",
    				c, dst, print_primes(ps, dst))
    		}
    	}
    }
     
    func check_primes(ps []int, f []int) bool {
    	for i := 0; i < len(f)-1; i++ {
    		if !valid_primes_pairs(ps, f[:i+1], f[i+1]) {
    			return false
    		}
    	}
    	return true
    }
     
    func print_primes(ps []int, f []int) (s string) {
    	for i, j := range f {
    		if i+1 < len(f) {
    			s += fmt.Sprint(ps[j], ",")
    		} else {
    			s += fmt.Sprint(ps[j])
    		}
    	}
    	return
    }
     
    func print_concat_primes(ps []int, f []int) (s string) {
    	gen := combin.NewCombinationGenerator(len(f), 2)
    	for gen.Next() {
    		d := gen.Combination(nil)
    		id1, id2 := f[d[0]], f[d[1]]
    		s += fmt.Sprintf("%v%v ", ps[id1], ps[id2])
    		s += fmt.Sprintf("%v%v ", ps[id2], ps[id1])
    	}
    	return s
    }
     
    func valid_primes_pairs(ps []int, h []int, g int) bool {
    	for _, v := range h {
    		if k := concat(ps[v], ps[g]); !IsPrime(k) {
    			return false
    		}
    		if k := concat(ps[g], ps[v]); !IsPrime(k) {
    			return false
    		}
    	}
    	return true
    }
     
    func concat(h, g int) int {
    	y := fmt.Sprintf("%v%v", h, g)
    	n, _ := strconv.Atoi(y)
    	return n
    }
     
    // primes is a cache of the first few prime numbers
    var primes_cache []int
     
    func init() {
    	// Cache the first 1,229 prime numbers (i.e. all primes <= 10,000)
    	primes_cache = primes.Sieve(5_000_000_000)
    }
     
    func IsPrime(n int) bool {
    	pMax := primes_cache[len(primes_cache)-1]
    	if n <= pMax {
    		// If n is prime, it must be in the cache
    		i := sort.SearchInts(primes_cache, n)
    		return n == primes_cache[i]
    	}
    	return primes.IsPrime(n)
    }
    Le go.mod

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module a.a
     
    go 1.21.1
     
    require (
    	github.com/fxtlabs/primes v0.0.0-20150821004651-dad82d10a449
    	github.com/pkg/profile v1.7.0
    	gonum.org/v1/gonum v0.14.0
    )
     
    require (
    	github.com/felixge/fgprof v0.9.3 // indirect
    	github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
    )
    Bonne journée.

  11. #11
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 295
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 295
    Par défaut
    J'aime ce problème. Quand on prend un fichier avec les nombres premiers jusqu'à 1 milliard, c'est là qu'il faut optimiser. On parle quand même de 50 milliards de nombres ! Du coup, il faut créer les couples avec délicatesse en tenant compte de la longueur.

    Nom : capture.png
Affichages : 285
Taille : 21,2 Ko

    On va répartir les nombres premiers en fonction de leur longueur. Le fichier p3.txt contient les nombres premiers de 3 chiffres, par exemple.
    Voici le nouveau code pour créer les couples (en temps raisonnable) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    for ((i=1;i<=9;i++))
    do
            for ((j=$i;j<=9;j++))
    do
                    somme=$(($i+$j))
            if [ $somme -lt 10 ]
                    then
                            awk '(FNR==1){fic++;} (fic==1){s[$1]++;} (fic==2){t[$1]++;} (fic==3){for (p in t) if (int(p)<int($1)) if ((s[p""$1]!="")&&(s[$1""p]!="")) print p,$1;}' p$somme.txt p$i.txt p$j.txt > cp${i}p$j.txt
                    fi
            done
    done
     
    cat cp*  > couples.txt
    Et pour étendre ces n-uplets, calculer un score est trop long. On va donner trop d'importance à des cas qui méritent la poubelle. Au lieu de cela, prenons le dernier nombre du n-uplet (le plus grand, normalement), listons les nombres qu'il accepte, et vérifions que ces candidats fonctionnent avec les autres nombres du n-uplet. On obtient un résultat en temps raisonnable.
    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
    #!/usr/bin/awk -f
     
    BEGIN{
            SUBSEP="M";
    }
     
    (FNR==NR){
            q[$1]++;
            c[$1,q[$1]]=$2;
            v[$0]++;
            next;
    }
     
    {
            for (i=1;i<=q[$NF];i++)
            {
                    m=c[$NF,i];
                    bon=1;
                    for (r=1;r<NF;r++)
                    {
                            if (v[$r" "m]!=1)
                                    bon=2;
                            if (bon==2)
                                    break;
                    }
                    if (bon==1)
                            print $0,m;
            }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ----- quintuplets -----
    13 5197 5701 6733 8389
     
    real    3m59,725s
    user    3m48,781s
    sys     0m10,844s
    Avec ce seul quintuplet, on ne peut pas atteindre 100 000 (seulement 26033).

    Avec les quadruplets, le plus proche qui dépasse semble être (1231, 5323, 6037, 87433) qui donne 100024.

  12. #12
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Bonjour,

    Quand on prend un fichier avec les nombres premiers jusqu'à 1 milliard, c'est là qu'il faut optimiser. On parle quand même de 50 milliards de nombres !
    Oui, mais vous n'aurez jamais assez de mémoire disponible
    pour garder en mémoire l'ensemble (infini) des nombres premiers.

    Les cas qui méritent la poubelle, au delà d'un certain seuil
    ne peuvent être évités et vont nécessairement monopoliser les ressources de la machine.

    Du coup, il faut créer les couples avec délicatesse en tenant compte de la longueur.
    Pour k=5 les indices commencent à [0,1,2,3,4], les itérations suivante seront nécessairement
    [0,1,2,3,5], [0,1,2,3,6] ect ou [0,1,3,4,5], [0,1,4,5,6], selon le sens du parcours.

    Après, peut être que le couple [0,2....] ne valide pas les règles de départ (la concaténation),
    et qu'il est donc inutile de poursuivre au delà, sauter directement à [0,3...]

    Finalement, comme je suis partisan que cette solution est orientée cpu, et non mémoire,
    je suggère de paralléliser les goulets d'étranglements sur la validation des nombres premiers.
    Chaque chiffre de l'indice 0 sert de point de départ à un nouveau calcul,
    on s'arrête au moment d'incrémenter cet indice.

    Je n'ai que 4 thread avec mon vieux PC,
    mais il est toujours aussi bon, dommage que ldlc ne produise plus ce genre de bécane en corei7,
    sur des configurations plus récente on gagne d'autant que la machine est montée comme un taureau.

    Maintenant, oui, très clairement, les règles de départ de l'exo de l'OP ne m'intéresse qu'à la marge,
    c'était surtout la navigation combinatoire que je voulais explorer.

    * Par ailleurs, au doigt mouillé, pour k=5, il semble inutile de tenter d'explorer les solutions
    dont les NP d'indice 0 sont > 20_000, NP[1]>20_000, NP[2]>20_000 etc (faudrait réfléchir à ce chiffre de 20_000, c'est une cible mouvante),
    puisque l'addition du reste sera nécessairement dans la tranche toujours plus haute des résultats > 100 000.

    Bonne journée.

  13. #13
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 238
    Par défaut
    Je réponds uniquement au post n°4, celui où tu donnes ton code.
    En Python, il faut à tout prix éviter les boucles. Je ne programme jamais en Python, et donc je ne vais pas savoir te donner les bonnes syntaxes, mais il faut manipuler des tableaux.
    Si on reste sur la recherche de quadruplets, tu as déjà trouvé une solution, et donc tu peux tester une autre façon de programmer, et voir la différence.

    En gros, ton programme Python devrait quasiment se réduire à 4 lignes.
    Tableau_1 = [ la liste des premiers inférieurs à un certain plafond]
    Tableau_2 = Tableau_1 x Tableau_1 , avec i1<i2 et i1||i2 premier et i2||i1 premier
    Tableau_4 = Tableau_2 x Tableau_2 , avec i2<i3 et i2||i3 premier et ... et ...
    Min4 = Mini (Tableau_4, somme des 4 éléments)
    Les outils appelés par Python pour croiser 2 très gros tableaux en filtrant (commande Pipe) sont en C++, des millions de fois plus rapide que des boucles en Python.

    Tu peux éventuellement faire des boucles, pour utiliser tes fichiers 'par longueur de nombre'. Donc des petites boucles de 1 à 8 ou 9, ok.

    Et enfin, tu peux exploiter une propriété (la règle de 3)
    Les nombres premiers peuvent être découpés en 3 groupes :
    - le nombre 3, tout seul
    - les nombres premiers de la forme 3k+1
    - les nombres premiers de la forme 3k+2
    Si tu prends un nombre du groupe 2 et un du groupe 3, forcément la concaténation de ces 2 nombres sera un multiple de 3.

    Donc tu peux faire 2 analyses. Une en prenant comme univers le nombre 3 et les nombres premiers du type 3k+1
    Puis une en prenant comme univers le nombre 3 et les nombres premiers du type 3k+2

  14. #14
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Bonjour,

    En bidouillant des trucs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ go run . -n 10_0000 -k 5
    2023/12/05 20:55:13 profile: cpu profiling enabled, cpu.pprof
      =>3,28277,44111,70241,78509  =>  221141
    .... 5
    .... 7
      =>7,61,25939,26893,63601  =>  116501
    .... 11
    .... 13
      =>13,829,9091,17929,72739  =>  100601
    [.... ça continue pour chaque tranche....]
    Ce serait tout de même plus simple si on avait les solutions
    pour n=1000 k=3 / n=1000 k=4
    Là c'est parti pour gratter encore un peu, mais pas quelques mois.

    Bonne journée

  15. #15
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 656
    Par défaut
    Bonjour MarvinLeRouge,
    Citation Envoyé par MarvinLeRouge Voir le message
    ...Pourrais tu réexpliquer ton algo ? Notamment la partie concernant la division avec le modulo.
    Désolé mais, je viens juste de voir ton message. La division et le modulo servent juste à récupérer 2 nombres constituant un troisième. Supposons un nombre n= 1234567 (qu'il soit premier n'est pas utile pour l'explication). Log10(n)/2 = pwr10 = 6.09151/2 = 3.045 -> 4 donc d=104 = 10000.
    1) d=104, 1234567 div 104 = 123, 1234567 mod 104 = 4567 (div pour division entière) : KO car 123 non premier
    2) d=105, 1234567 div 105 = 12, 1234567 mod 105 = 34567 : KO car 12 non premier
    3) d=106, 1234567 div 106 = 1, 1234567 mod 10[SUP]56/SUP] = 234567 : KO car 1 non premier

    Div/mod peut être réduit à une seule opération dans la plupart des langages ou par la grâce du compilateur car c'est la même opération, la division entière, qui donne à la fois le quotient et le reste (aka le modulo).

    Le test de primalité peut utiliser une recherche dichotomique dans la liste des premiers (en initialisant un tableau qui donne l'indice du plus grand premier de k chiffres cela accélère cette recherche), mais pour être efficiente cette recherche devrait s'exercer sur une liste en mémoire. A défaut un test de primalité calculé sera certainement à préférer.

    Cependant, il semble que la solution de Flodelarab soit meilleure bien qu'elle paraisse (à vérifier) également en O(n.log(n)) - on ne peut dépasser pour le premier terme sqrt(nmax) - mais parce qu'elle évite des opérations coûteuses comme log et division. Ceci étant, si Python est parfait pour un PoC, ce n'est vraisemblablement pas la voie de l'optimisation.

    Ajout : on peut éviter le calcul du log, sauf le premier, car dans l'algorithme proposé, on part du plus grand premier de la liste et on décroit régulièrement. Il suffit donc d'un test < 10pwr10 pour décider si pwr10 doit diminuer d'une unité et qu'il faut recalculer d.

    Salut

  16. #16
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Bonjour,

    Je poste ma version mise au propre avec un peu de sérieux,
    histoire de ne pas rester sur l'horreur précédente.

    Il y a des vérifications à faire, mais l'idée est là.

    Un itérateur de NP, des chemins à évincer,
    des bornages à droite à gauche sont des pistes d'améliorations.

    C'est pas terrible le PO qui attend que ça tombe du ciel.

    Bonne journée.

    Code go : 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
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
     
    package main
     
    import (
    	"bufio"
    	"flag"
    	"fmt"
    	"io"
    	"os"
    	"sort"
    	"strconv"
    	"strings"
    	"sync"
    	"time"
     
    	"github.com/fxtlabs/primes"
    	"github.com/pkg/profile"
    	"golang.org/x/text/language"
    	"golang.org/x/text/message"
    )
     
    func main() {
     
    	n := flag.Int("n", 100_000, "n")
    	k := flag.Int("k", 5, "k")
    	path := flag.String("path", "-", "path")
    	prof := flag.Bool("prof", true, "profile")
    	dbg := flag.Bool("debug", false, "debug")
    	vrb := flag.Bool("verbose", true, "verbose")
    	mt := flag.Bool("mt", false, "parallel")
    	cache := flag.Int("cache", -1, "cache")
     
    	flag.Parse()
     
    	debug = *dbg
    	verbose = *vrb
     
    	var dst io.Writer = os.Stdout
    	if p := strings.TrimSpace(*path); p != "-" && p != "" {
    		f, err := os.Create(p)
    		if err != nil {
    			panic(err)
    		}
    		dst = f
    		defer f.Close()
    	}
     
    	if *cache > -1 {
    		primes_cache = load_primes(*cache)
    	} else {
    		k := 1
    		for i := len(strconv.Itoa(*n/10)) * 2; i > 0; i-- {
    			k *= 10
    		}
    		primes_cache = load_primes(k)
    	}
     
    	st := time.Now()
    	defer func() {
    		fmt.Fprintln(os.Stderr, time.Since(st))
    	}()
     
    	if *prof {
    		defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
    	}
     
    	out := dst
    	fn := combin_primes
    	if *mt {
    		fn = combin_primes_mt
    	}
    	print_res := func(res []int) {
    		fmt.Fprint(out, "  => ")
    		s := 0
    		for _, r := range res[:len(res)-1] {
    			fmt.Fprintf(out, "%v,", r)
    			s += r
    		}
    		fmt.Fprintf(out, "%v", res[len(res)-1])
    		s += res[len(res)-1]
    		fmt.Fprintf(out, "  => %v %v\n", check_primes(res), s)
    	}
    	allres := [][]int{}
    	fn(*n, *k, func(res []int) {
    		print_res(res)
    		t := make([]int, len(res))
    		copy(t, res)
    		allres = append(allres, t)
    	})
     
    	if p := strings.TrimSpace(*path); p != "-" && p != "" {
    		fmt.Println()
    		fmt.Println()
    	}
    	for _, res := range allres {
    		print_res(res)
    	}
    }
     
    var verbose = !true
    var debug = !true
     
    func combin_primes(n, k int, cb func([]int)) {
     
    	ps := load_primes(n)
    	u := len(ps)
    	if debug {
    		fmt.Fprintln(os.Stderr, "n", n)
    		fmt.Fprintln(os.Stderr, "k", k)
    		fmt.Fprintln(os.Stderr, "u", u)
    	}
    	res := make([]int, k)
    	idx := make([]int, k)
    	for i := range idx {
    		idx[i] = i
    	}
    	idx[0]++
    	l := k - 1
    	c := 1
    	var best_sum int
    	var best_sumk1 int
    	for idx[0] <= u-k && (best_sumk1 < 1 || ps[idx[0]] <= best_sumk1) {
    		ok := valid_primes_pairs(ps, idx[:c], idx[c])
    		if debug {
    			if ok {
    				fmt.Fprintf(os.Stderr, "c=%v ", c)
    				fmt.Fprintf(os.Stderr, "idx=%-20v ", fmt.Sprint(idx[:c+1]))
    				fmt.Fprintf(os.Stderr, "primes=%v ", print_primes(ps, idx[:c+1]))
    				fmt.Fprintln(os.Stderr)
    				<-time.After(time.Second / (2 * 5))
    			}
    		}
    		if ok {
    			if c == l {
    				s := 0
    				for i, v := range idx {
    					res[i] = ps[v]
    					s += res[i]
    				}
    				if s >= n && (best_sum < 1 || best_sum >= s) {
    					best_sum = s
    					best_sumk1 = s / k
    					cb(res)
    					c--
    				}
    			} else {
    				c++
    				if c == l {
    					s := 0
    					for _, v := range idx[:c] {
    						s += ps[v]
    					}
    					n := sort.SearchInts(ps[idx[c]:], (n-s)/(k-c)) - 1
    					if n > idx[c-1] {
    						idx[c] = n
    					} else {
    						idx[c] = idx[c-1]
    					}
    				} else {
    					idx[c] = idx[c-1]
    				}
    			}
    		}
    		if !ok && c == l && best_sum > 0 {
    			s1 := 0
    			for _, v := range idx {
    				s1 += ps[v]
    			}
    			if s1 > best_sum {
    				c--
    			}
    		}
    		idx[c]++
    		// if c > 0 && res[c] > 0 && ps[idx[c]] >= res[c] {
    		// 	c--
    		// 	idx[c]++
    		// }
    		for c > 0 && idx[c] >= u-(k-c) {
    			c--
    			idx[c]++
    		}
    		if c == 0 {
    			c = 1
    			idx[c] = idx[c-1] + 1
    			if verbose {
    				fmt.Fprintln(os.Stderr, "....", ps[idx[0]])
    			}
    		}
    	}
    }
     
    var mutex sync.Mutex
    var gbest_sum int
    var gbest_sumk1 int
     
    func combin_primes_mt(n, k int, cb func([]int)) {
    	ps := load_primes(n)
    	lmt := make(chan struct{}, 8)
    	c := make(chan []int, 10)
    	var wg sync.WaitGroup
    	wg.Add(1)
    	go func() {
    		defer wg.Done()
    		for i := 0; i < len(ps)-k; i++ {
    			wg.Add(1)
    			i := i
    			lmt <- struct{}{}
    			go func() {
    				defer wg.Done()
    				combin_primes_start(ps, i, n, k, func(r []int) {
    					t := make([]int, k)
    					copy(t, r)
    					c <- t
    				})
    				<-lmt
    			}()
    		}
    	}()
    	go func() {
    		wg.Wait()
    		close(c)
    	}()
    	for o := range c {
    		cb(o)
    	}
    }
     
    func combin_primes_start(ps []int, st, n, k int, cb func([]int)) {
    	u := len(ps)
    	if st > u-k {
    		return
    	}
    	if debug {
    		fmt.Fprintln(os.Stderr, "n", n)
    		fmt.Fprintln(os.Stderr, "k", k)
    		fmt.Fprintln(os.Stderr, "u", u)
    	}
    	res := make([]int, k)
    	idx := make([]int, k)
    	for i := range idx {
    		idx[i] = st + i
    	}
    	if st == 0 {
    		idx[0]++
    	}
    	l := k - 1
    	c := 1
    	mutex.Lock()
    	best_sum := gbest_sum
    	best_sumk1 := gbest_sumk1
    	mutex.Unlock()
    	for idx[0] <= u-k && (best_sumk1 < 1 || ps[idx[0]] <= best_sumk1) {
    		ok := valid_primes_pairs(ps, idx[:c], idx[c])
    		if debug {
    			if ok {
    				fmt.Fprintf(os.Stderr, "c=%v ", c)
    				fmt.Fprintf(os.Stderr, "idx=%-20v ", fmt.Sprint(idx[:c+1]))
    				fmt.Fprintf(os.Stderr, "primes=%v ", print_primes(ps, idx[:c+1]))
    				fmt.Fprintln(os.Stderr)
    				<-time.After(time.Second / (2 * 5))
    			}
    		}
    		if ok {
    			if c == l {
    				s := 0
    				for i, v := range idx {
    					res[i] = ps[v]
    					s += res[i]
    				}
    				if s >= n && (best_sum < 1 || best_sum >= s) {
    					best_sum = s
    					best_sumk1 = s / k
    					mutex.Lock()
    					if gbest_sum < 1 || best_sum < gbest_sum {
    						gbest_sum = best_sum
    						gbest_sumk1 = best_sumk1
    					}
    					mutex.Unlock()
    					cb(res)
    					c--
    				}
    			} else {
    				c++
    				if c == l {
    					s := 0
    					for _, v := range idx[:c] {
    						s += ps[v]
    					}
    					n := sort.SearchInts(ps[idx[c]:], (n-s)/(k-c)) - 1
    					if n > idx[c-1] {
    						idx[c] = n
    					} else {
    						idx[c] = idx[c-1]
    					}
    				} else {
    					idx[c] = idx[c-1]
    				}
    			}
    		}
    		if !ok && c == l && best_sum > 0 {
    			s1 := 0
    			for _, v := range idx {
    				s1 += ps[v]
    			}
    			if s1 > best_sum {
    				c--
    			}
    		}
    		idx[c]++
    		// if c > 0 && res[c] > 0 && ps[idx[c]] >= res[c] {
    		// 	c--
    		// 	idx[c]++
    		// }
    		for c > 0 && idx[c] >= u-(k-c) {
    			c--
    			idx[c]++
    		}
    		if c == 0 {
    			// c = 1
    			// idx[c] = idx[c-1] + 1
    			if verbose {
    				fmt.Fprintln(os.Stderr, "....", ps[idx[0]])
    			}
    			return
    		}
    	}
    }
     
    func check_primes(f []int) bool {
    	for i := 0; i < len(f)-1; i++ {
    		if k := concat(f[0], f[1]); !IsPrime(k) {
    			return false
    		}
    		if k := concat(f[1], f[0]); !IsPrime(k) {
    			return false
    		}
    	}
    	return true
    }
     
    func print_primes(ps []int, f []int) (s string) {
    	for i, j := range f {
    		if i+1 < len(f) {
    			s += fmt.Sprint(ps[j], ",")
    		} else {
    			s += fmt.Sprint(ps[j])
    		}
    	}
    	return
    }
     
    func valid_primes_pairs(ps []int, h []int, g int) bool {
    	for _, v := range h {
    		if k := concat(ps[v], ps[g]); !IsPrime(k) {
    			return false
    		}
    		if k := concat(ps[g], ps[v]); !IsPrime(k) {
    			return false
    		}
    	}
    	return true
    }
     
    func concat(left, right int) int {
    	i := 1
    	for i <= right {
    		i *= 10
    	}
    	left *= i
    	return left + right
    }
     
    func load_primes(n int) []int {
    	nn := message.NewPrinter(language.English).Sprintf("%d", n)
    	nn = strings.Replace(nn, ",", "_", -1)
    	name := fmt.Sprintf("primes_%v.txt", nn)
    	j := len(strconv.Itoa(n / 10))
    	st, err := os.Stat(name)
    	if os.IsNotExist(err) {
    		f, err := os.Create(name)
    		if err != nil {
    			panic(err)
    		}
    		defer f.Close()
    		dst := bufio.NewWriter(f)
    		defer dst.Flush()
    		z := fmt.Sprintf("%%%vv\n", j)
    		ps := primes.Sieve(n)
    		for _, p := range ps {
    			fmt.Fprintf(dst, z, p)
    		}
    		return ps
    	}
    	r, err := os.Open(name)
    	if err != nil {
    		panic(err)
    	}
    	k := st.Size() / int64(1+j)
    	sc := bufio.NewScanner(bufio.NewReader(r))
    	ps := make([]int, k)
    	var i int
    	for sc.Scan() {
    		t := strings.TrimSpace(sc.Text())
    		n, err := strconv.Atoi(t)
    		if err != nil {
    			panic(err)
    		}
    		ps[i] = n
    		i++
    	}
    	return ps
    }
     
    // primes is a cache of the first few prime numbers
    var primes_cache []int
     
    func IsPrime(n int) bool {
    	pMax := primes_cache[len(primes_cache)-1]
    	if n <= pMax {
    		// If n is prime, it must be in the cache
    		i := sort.SearchInts(primes_cache, n)
    		return n == primes_cache[i]
    	}
    	return primes.IsPrime(n)
    }

  17. #17
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 656
    Par défaut
    Bonjour unanonyme,

    Citation Envoyé par unanonyme Voir le message
    ...C'est pas terrible le PO qui attend que ça tombe du ciel...
    Ce qui justifie (!?) ma paresse à proposer du code .

    Salut

  18. #18
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Ce qui justifie (!?) ma paresse à proposer du code .
    Bonjour Guesset,

    vous êtes trop intelligent,
    s'étaler à ce sujet ne serait que du rabâchage sans conséquences.

    Bonne journée.

  19. #19
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 238
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 238
    Par défaut
    Pour ma part, je bricole de temps en temps 2 ou 3 trucs en Go, et je suis content de voir du code en go.
    J'avais commencé à éplucher le 1er programme (pour apprendre, pas pour juger), et il y avait des trucs qui me paraissaient 'crados'... je suis rassuré de voir que UnAnonyme a posté une version plus propre. Je vais donc reprendre l'apprentissage.

    Visiblement MarvinLeRouge a un niveau beaucoup plus faible que vous en programmation. Il programme en Python, soit. Python peut donner de très bons résultats quand on est un très bon programmeur Python, en manipulant des dataframes ou des trucs du genre.
    Vous ne jouez pas du tout dans la même catégorie que MarvinLeRouge.

  20. #20
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    Pour ma part, je bricole de temps en temps 2 ou 3 trucs en Go, et je suis content de voir du code en go.
    J'avais commencé à éplucher le 1er programme (pour apprendre, pas pour juger), et il y avait des trucs qui me paraissaient 'crados'... je suis rassuré de voir que UnAnonyme a posté une version plus propre. Je vais donc reprendre l'apprentissage.

    Visiblement MarvinLeRouge a un niveau beaucoup plus faible que vous en programmation. Il programme en Python, soit. Python peut donner de très bons résultats quand on est un très bon programmeur Python, en manipulant des dataframes ou des trucs du genre.
    Vous ne jouez pas du tout dans la même catégorie que MarvinLeRouge.
    Bonjour,

    oui c'était très sale. Je n'ai rien à vous apprendre, je n'ai même pas le bac.

    Dirigez vous plutôt vers ce repo pour apprendre de bonne techniques

    https://github.com/klauspost/compress/tree/master/s2

    A ré implémenter c'est sympa, je n'ai jamais pu obtenir d'aussi bon résultats...

    Bonne journée.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 6
    Dernier message: 30/03/2015, 15h20
  2. Recherche de nombres premiers
    Par jca dans le forum Codes sources à télécharger
    Réponses: 0
    Dernier message: 03/02/2013, 17h44
  3. recherche de nombre premier
    Par hazaki dans le forum Débuter
    Réponses: 4
    Dernier message: 27/10/2010, 19h55
  4. Réponses: 15
    Dernier message: 30/07/2008, 18h06

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