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

Commentaires

  1. Avatar de dourouc05
    • |
    • permalink
    Pour préciser : il y a beaucoup de compléments à Unitful.jl destinés à des domaines d'application pas forcément génériques.

    Par contre, je ne pense pas qu'on puisse encore conseiller des paquets comme Units.jl (https://github.com/timholy/Units.jl).
  2. Avatar de danielhagnoul
    • |
    • permalink
    Il s'agit de : trouver la position et la longueur de la plus longue séquence de lettres minuscules d'un mot de passe.

    Le titre du billet est bloqué, impossible de mettre le titre complet.
  3. Avatar de danielhagnoul
    • |
    • permalink
  4. Avatar de f-leb
    • |
    • permalink
    Excellent ! Et comme dans d'autres rubriques, tu peux proposer des exercices, et même des Quiz pour s'entraîner sur Julia.

    C'est bien parti, bonne continuation
  5. Avatar de dourouc05
    • |
    • permalink
    L'exemple que tu reprends, outre son âge (depuis 2016, Julia a énormément évolué, mais globalement les résultats n'ont pas changé dans ce cas), parle d'un cas un peu différent : donner des types quand on est sûr de ce qu'on va y stocker. L'idéal serait plutôt d'écrire le code avec des paramètres comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function count_numbers(v::Vector{T}) where T
        n = length(v)
        d = Dict{T, Int}()
        for i = 1:n 
            d[v[i]] = get(d, v[i], 0) + 1
        end 
        return d 
    end
    count_numbers2 est une écriture très foireuse : Julia ne râlera pas lors de l'appel de la fonction avec un vecteur de nombres à virgule flottante, mais ça plantera lors de l'ajout dans le dictionnaire… Mon code évitera ce problème, tout en ayant une performance similaire (d'après mes tests préliminaires avec la version 1.5.0, ça prend le même temps et un peu moins de mémoire que count_numbers2). Surtout, on peut utiliser cette fonction avec d'autres types de nombres ou même autre chose (un vecteur de distributions de probabilités, par exemple), ce qui n'est pas du tout le cas avec count_numbers2.
  6. Avatar de danielhagnoul
    • |
    • permalink
    Je ne suis pas encore assez compétent en Julia pour discuter de ce sujet avec toi, mais j'ai trouvé une référence de 2016.

    Performance and Concrete Types in Julia posted by PAUL STEY on JULY 20, 2016

    Extrait de la fin de cet article :

    Les résultats ci-dessus sont vraiment frappants. En termes de vitesse, nous voyons que notre version de type concret de la fonction est environ 4x plus rapide que notre version de type non concret (d'ailleurs, c'est environ 14x plus rapide que Python pour des vecteurs de longueur 10 millions). Nous notons également que la vitesse évolue linéairement (ou un peu mieux) avec la taille d'entrée.

    Mais ce que je trouve fascinant, c'est que nos allocations et notre utilisation de la mémoire sont en fait constantes par rapport à la taille d'entrée! Dans notre version non concrète, notre appel de fonction alloue 300 Mo de mémoire sur le vecteur de longueur 10 millions; et la version de type béton n'utilise que 768 octets .

    Cela m'a bouleversé quand je suis tombé dessus. Cela ressemble fondamentalement à de la magie. La leçon ici semble claire: lorsque les performances sont critiques, faites tout ce que vous pouvez pour utiliser des types concrets.
  7. Avatar de dourouc05
    • |
    • permalink
    Plus vous utilisez votre système de typage, plus il fonctionne pour vous.
    … et, moins on utilise le système de typage, mieux Julia fonctionne ! C'est comme ça qu'on peut résoudre des équations différentielles sur des nombres complexes ou des erreurs de mesure, par exemple. Si DifferentialEquations.jl (entre autres) forçaient à utiliser des Float64 partout, ça ne pourrait pas marcher aussi bien.

  8. Avatar de danielhagnoul
    • |
    • permalink
    Merci ! C'est modifié. Pour le fichier HTML il faut sans doute effacer le cache du navigateur pour voir la nouvelle version.
  9. Avatar de dourouc05
    • |
    • permalink
    Petite remarque concernant le titre (billet et fichier HTML) : tu fais un ajustement de courbe, pas l'inverse .
  10. Avatar de danielhagnoul
    • |
    • permalink
    @dourouc05 : bonjour mon ami, un grand merci pour tes critiques constructives. J'en ai tenu compte dans la nouvelle version de la solution proposée.

    L'énoncé de l'exercice est réel, les fonctions et leurs ordres de test sont explicitement demandés (voir : https://www.developpez.net/forums/d2.../#post11464396)
  11. Avatar de dourouc05
    • |
    • permalink
    Tu devrais nommer les variables d'instance tout en bas de casse (https://www.python.org/dev/peps/pep-...variable-names), vu que tout le code Python respecte la norme PEP8 (l'un des très rares langages avec un guide stylistique commun !). Aussi, pour cacher ces variables d'instance, ça serait mieux de commencer leur nom avec un _, histoire d'indiquer clairement que ces variables ne sont pas censées accessibles en dehors de la classe elle-même : en dehors du module, ça devient difficile d'y accéder directement, il ne reste que l'interface que tu définis.

    Ça donnerait :

    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
    class Produit:
        def __init__(self, code, nom, prix):
            self._code = code
            self._nom = nom
            self._prix = prix
     
        @property
        def code(self):
            return self._code
     
        @property
        def nom(self):
            return self._nom
     
        @property
        def prix(self):
            return self._prix
     
        @Prix.setter
        def prix(self, prix):
            self._prix = prix
    Ensuite, pour le reste de la solution, je ne suis pas du tout convaincu par tes fonctions saisir_. En fait, il s'agit juste d'appeler un constructeur, alors que ta spécification de ces fonctions est : "Écrire une fonction saisir_ qui permet à l’utilisateur de saisir…" Je m'attendrais plus à l'utilisation de input(), vu la spécification.

    afficher_produit ne devrait pas être une fonction indépendante, mais plutôt une méthode de la classe Produit, plus précisément nommée __str__ pour suivre les normes de Python (https://stackoverflow.com/a/2626364/1066843). Ainsi, afficher le produit avec un print te donnera directement la bonne chaîne. D'ailleurs, ton implémentation ne correspond pas à ta spécification : tu devrais afficher une chaîne de caractères et non en retourner une.
  12. Avatar de Stellabrige
    • |
    • permalink
    Bonjour moi j'ai un problème avec le langage c
  13. Avatar de danielhagnoul
    • |
    • permalink


    Bien vu, merci.

    Une erreur de débutant en Python, oublier le +1 : for index in range(n, len(brin)+1, n):
    Mis à jour 11/03/2020 à 18h36 par danielhagnoul
  14. Avatar de rawsrc
    • |
    • permalink
    salut,

    t'es sûr de ton algo parce qu'après un simple contrôle par calcul mental, je n'arrive pas au point de départ : ton brin fait 48 caractères.
    Quand on fait la somme des fréquences de tes résultats : on arrive à 2 x 23 = 46 et 3 x 15 = 45, euh t'aurais pas perdu des brins au passage ?
    J'ai refait le même boulot en PHP pour vérifier :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $brin = 'ACCTAGCCATGTAGAATCGCCTAGGCTTTAGCTAGCTCTAGCTAGCTG';
    $freq_len2 = array_count_values(str_split($brin, 2));
    $freq_len3 = array_count_values(str_split($brin, 3));
    et il te manque bien le dernier brin dans les deux cas de figure.
    Mis à jour 11/03/2020 à 14h53 par rawsrc
  15. Avatar de bistouille
    • |
    • permalink
    Salut.

    Tu triches

    Déjà le fait de faire un test en passant 50 valeurs à la fonction désavantage évidemment combinations qui va faire 1225 appels à _pgcd. Puis faire des tests sur de petits nombres avantage aussi grandement ta fonction

    Il suffit de tester avec moins de nombres, des nombres plus grand et impairs.
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    lst = sample(range(10_001, 100_001, 2), 5)
    Et voilà malgré toutes les combinaisons c'est déjà beaucoup plus rapide qu'avec la fonction diviseurs. Et encore plus efficient en utilisant des nombres premiers.

    Ce qui est lent, c'est de tester autant de fois qu'il y a de combinaisons, O(n-1) vs O(2^n) (euh... si je ne me goure pas), alors il suffit de changer itertools.permutation par itertools.accumulate dans pgcd.
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    return tuple(accumulate(values, _pgcd))[-1]

    Et là, c'est assez proche de ton second script avec le while
  16. Avatar de danielhagnoul
    • |
    • permalink
    La fonction diviseurs() était mon point de départ, mon besoin réel. La recherche du PGCD de plusieurs nombres est venue en bonus.
  17. Avatar de bistouille
    • |
    • permalink


    Encore de passage sur un de tes billets
    Ce script est beaucoup trop lent, normal car tu calcules tous les diviseurs de chaque nombres, d'ailleurs la fonction diviseurs n'est pas du tout géniale.

    J'ai fait un simple test avec de grands nombres comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    base = 53 * 47 * 19 * 1001
    values = (base * 71, base * 109, base * 109 * 71)
    Et ça mouline grave avec ta fonction pgcd_n

    Alors qu'avec une fonction comme

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def pgcd(*values) :
        from itertools import combinations
        def _pgcd(a, b) :
            m = a % b
            while m :
                a, b = b, m
                m = a % b
            return b
        return min(_pgcd(a, b) for a, b in combinations(values, 2))

    Le résultat est instantané.
    Je n'ai rien inventé, cet algo est connu pour trouver rapidement le PGCD de 2 nombres
  18. Avatar de rawsrc
    • |
    • permalink
    Salut,

    j'ai voulu vérifier ce que cette ventilation représentait en terme de code en PHP :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?php
     
    $count  = $devises = ['500' => 0, '200' => 0, '100' => 0, '50' => 0, '20' => 0, '10' => 0, '5' => 0, '2' => 0, '1' => 0, '0.50' => 0, '0.20' => 0, '0.10' => 0, '0.05' => 0, '0.02' => 0, '0.01' => 0];
    $equipe = ['Dupont' => 4257.12, 'Durand' => 2024.78, 'Pierre' => 814.36];
     
    foreach ($equipe as $nom => $salaire) {
        $salaire *= 100;
        foreach ($devises as $d => &$nb) {
            $d         *= 100;
            $nb         = intdiv($salaire, $d);
            $salaire   -= $d * $nb;
            $count[$d] += $nb;      // nombre total de devises nécessaires [devise => nombre total]
        }
        $ventil[$nom] = $devises;   // [nom => [devise => nombre]]
    }
    Pour faciliter le truc, j'ai effectivement retenu la multiplication par 100

    Perso, je trouve que ça pique :
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for dico in employes.values():
        for t in dico["composition"]:
            for lst in devises_total:
  19. Avatar de danielhagnoul
    • |
    • permalink


    J'ai utilisé round() pour ne pas utiliser la multiplication par 100.

    Depuis, j'ai découvert que la solution pythonique au problème d'arrondi monétaire c'est decimal : https://docs.python.org/fr/3.7/library/decimal.html
  20. Avatar de bistouille
    • |
    • permalink
    Une autre méthode est de multiplier par 100 salaire et numéraire.

    Approche simpliste.

    Code python : 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
    NUMERAIRES = (
        500, 200, 100, 50, 20, 10, 5, 2, 1,
        0.5, 0.10, 0.05, 0.02, 0.01
    )
     
    def repartition_numeraires(montant) :
        montant *= 100
        nums = {}
        i = 0
        while montant :
            n, montant = divmod(montant, NUMERAIRES[i] * 100)
            nums[NUMERAIRES[i]] = int(n)
            i += 1
        return nums
     
    items = (
        ('Dupond', 4257.12),
        ('Durand', 2024.78),
        ('Pierre', 814.36),
    )
    employes = {}
    for nom, montant in items :
        employes[nom] = dict(
            salaire=dict(
                montant=montant,
                numeraires=dict.fromkeys(NUMERAIRES, 0),
            ),
        )
     
    for nom in employes :
        salaire = employes[nom]['salaire']
        num = repartition_numeraires(salaire['montant'])
        salaire['numeraires'].update(num)
     
    somme_salaires = round(
        sum(e['salaire']['montant'] for e in employes.values()),
        2
    )
    print('somme salaires :', somme_salaires)
     
    numeraires = dict.fromkeys(NUMERAIRES, 0)
    for e in employes.values() :
        for v in numeraires :
            numeraires[v] += e['salaire']['numeraires'][v]
     
    print(numeraires)
    somme_numeraires = round(sum(k * v for k, v in numeraires.items()), 2)
    print('somme numéraires :', somme_numeraires)
Page 1 sur 3 123 DernièreDernière