Commentaires

  1. 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
  2. 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.
  3. 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
  4. 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:
  5. 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
  6. 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)
  7. Avatar de danielhagnoul
    • |
    • permalink
    Bonsoir

    Superbe simplification de mon code, bravo !
    Merci d'avoir posté cette élégante solution.
  8. Avatar de bistouille
    • |
    • permalink
    En utilisant la méthode get des dictionnaires, tu peux améliorer et réduire tes deux fonctions.

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def texte_vers_morse(texte):
        """Transforme un texte accentués, sans retour à la ligne, en morse"""
        texte = unicodedata.normalize('NFKD', texte).encode(
            'ASCII', 'ignore').decode('ASCII')
        morse = tuple(L2S.get(c.upper(), '') for c in texte)
        return ' '.join(morse)
     
    def morse_vers_texte(morse):
        """Transforme le code morse généré par texte_vers_morse() en texte ASCII"""
        lst = tuple(S2L.get(s, ' ') for s in morse.split(' '))
        return ''.join(lst)
  9. Avatar de Beginner.
    • |
    • permalink
    Salut,

    Je viens de voir ton billet...

    Et oui ce n'est pas forcément évident à faire pour un débutant...

    Je note l'usage de la fonction trunc : quotient = trunc(n / 16)...

    J'avais vu il y a quelques temps que la division entière pouvait aussi se faire avec l'opérateur // : quotient = n // 16...

    Je ne connais pas encore zip, il faudra que je regarde ça...
  10. Avatar de Nothus
    • |
    • permalink
    Entièrement d'accord avec tous les points indiqués par l'article.

    J'y ajoute mon grain de sel :

    (1) j'utilise addEventListener, et c'est une plaie pour une raison : il dédouble les fonctions (et c'est si c'est ma volonté d'avoir des doublons?), sans pouvoir lister ce qui existe déjà (on ne choisit pas). Pour le coup, un tableau de fonctions à appeler en callback m'aurait semblé plus indiqué pour une utilisation dans un contexte où souvent les scripts se chevauchent, permettant de retirer plus aisément les fonctions ajoutées (retirer une fonction anonyme c'est juste galère... ou alors je m'y prends mal ?!)

    (2) JS "confond" synchrone et asynchrone. Python a cette avantage que tu déclares une boucle d'événements, que tu peux contrôler, et qui finalement rend très transparent le contexte du code lorsqu'il est développé. JS c'est directement intégré à l'architecture du logiciel si j'ai tout bien suivi (?). Au quotidien, entre callback/setTimeout ou Promise, code synchrone et asynchone, c'est juste le foutoir. Avis très personnel qui n'engage évidemment que moi...

    (2') IndexedDB est un exemple parlant : la doc du MDN prévoit un abandon du synchrone, alors qu'on a mis en place les Workers pour éviter la complexité de l'asynchrone. Résultat on a le doublon Worker et des API plus ou moins asynchrones, non-normés. Je ne comprends pas la logique.

    Le problème de JS me semble être avant la "limite" de ce qu'il entend être, en ajustant ainsi ses qualités et ses défauts à un cadre plus rigide, particulièrement dans un contexte client Web.
  11. Avatar de jreaux62
    • |
    • permalink
    Bonjour,

    Si on va par là, il faut aussi tenir compte de la longitude et latitude.
  12. Avatar de danielhagnoul
    • |
    • permalink
    J'ai utilisé moment.js plutôt qu'une simple fonction JS parce que l'on peut mettre une règle nuit/jour différente dans chaque fichier local.

    Pour l'exemple j'ai utilisé une règle simpliste en me basant sur l'heure "légale" dans le local "fr".

    Rien n'empêche de définir des règles beaucoup plus sophistiquées en passant à la fonction la date complète au lieu de l'heure.
  13. Avatar de psychadelic
    • |
    • permalink
    un peu déçu...


    L'heure du début du jour (ou celle du début de la nuit) dépendent des coordonnées ou l'on veut ce placer sur le globe terrestre, et de la date dans l'année.
    Exemple : les nuits son plus longues en hivers dans l’hémisphère nord.

    https://fr.wikipedia.org/wiki/Dur%C3%A9e_du_jour

    Ces données restent de toutes façons imprécises par le calcul absolu et constamment (chaque jour) corrigées dans les dans les éphémérides par le Service international de la rotation terrestre et des systèmes de référence => https://fr.wikipedia.org/wiki/Servic...A9f%C3%A9rence

    Ce qu'il faut comprendre c'est que la terre ne tourne pas sur elle-même de façon régulière mais par accoups. c'est imperceptible, mais cet effet est principalement du aux déplacement des marrées. il y a donc un "bureau" chargé de vérifier la durée du jours et cette information est utile par exemple pour recalibrer le réseau GPS, mais aussi dans le cas de la navigation spatiale pour pointer correctement les antennes sur terre vers les sondes d'exploration, et dans ce cas se gourer d'un poil pour les viser peut coûter des millions ( exemple New Horizon ~= 500 M$)


    on peut aussi rajouter les faits que la terre oscille légèrement sur son axe, que l’ellipse de sa trajectoire comprend des phases d'accélération et de ralentissement suivant la distance Terre - Soleil qui est elle même faiblement perturbé par les positions des autres planètes du système solaire ( voir les travaux de J.Laskar) ...

    https://fr.wikipedia.org/wiki/Rotation_de_la_Terre
    https://fr.wikipedia.org/wiki/Temps_...coordonn%C3%A9

    https://ptaff.ca/soleil/
    http://hpiers.obspm.fr/eop-pc/index....ange_lang=true

    https://ssl21.secure-svr.com/leshorairesdusoleil_com/

    https://fr.wikipedia.org/wiki/New_Horizons
    https://fr.wikipedia.org/wiki/Liste_...ndes_spatiales
  14. Avatar de SylvainPV
    • |
    • permalink
    Le loose mode de Babel permet de bien simplifier le code ES5 produit, même s'il n'est pas 100% spec compliant et donc introduit un risque de régression. Après, les "horreurs" ne m'ont jamais trop dérangé puisque j'utilise Babel uniquement pour le build de production aux côtés de Uglify, donc j'ai un code imbitable dans tous les cas à la fin. Mais je n'ai jamais constaté de régression entre ES6 et ES5 transpilé. Le code est peut-être illisible, mais il fonctionne impec. Certes au prix de ~30/40% de taille de bundle et de coût à l'éxécution.

    Je pense que la technique du script module est un bon compromis qui devrait donner un résultat acceptable pendant quelques années, le temps qu'IE meurt pour de bon (allez on y croit). Les nouveaux navigateurs grand public ont tous des mises à jour auto, ça devrait réduire considérablement le travail de Babel avec le preset-env.

    Pour ce qui est de supprimer des parties du langage dans les versions de JS, je ne pense pas que ce soit une bonne idée. Il faut comprendre pourquoi ces parties sont obsolètes, avant de juger qu'elles doivent être éliminées. Par exemple, l'instruction `with` est coûteuse et confusante, et donc déconseillée à l'usage. Mais elle est utilisée en minification pour réduire la taille du code, dans des cas où le coût à la compilation est négligeable par rapport au gain en taille. Donc l'instruction reste utile, même s'il ne faut plus l'utiliser en développement. De la même façon, certaines instructions sont moins pratiques à l'usage mais plus performantes, comme les `getElementsBy`. Elles ont donc tout à fait leur place dans le code de bilbiothèques/frameworks, mais moins dans du code utilisateur.

    Au final, le "nettoyage" du langage est plus un travail à faire du côté de la formation, des linters et des précompilateurs, que du langage lui-même. Maintenir plusieurs subsets du langage au sein d'un compilateur JIT est aussi compliqué, voire davantage, que de maintenir le code des instructions dépréciées. Mais ça ne devrait surprendre personne, c'est une habitude en informatique de construire par-dessus les ruines du passé (cf modèle OSI).
  15. Avatar de danielhagnoul
    • |
    • permalink
    @SylvainPV :
    Il existe une solution pour distinguer les environnements "modernes" des dépassés, et utiliser directement du JS moderne tout en préservant la compatibilité grâce à Babel et aux polyfills: <script type="module"> et <script nomodule>.
    C'est pratique pour les utilisateurs qui utilisent ES2015+ et qui veulent fournir aux navigateurs obsolètes une solution de repli.

    Je connais et j'ai déjà utilisé. C'est justement à ces occasions que Babel produit ce que j'appelle des "horreurs".

    Si vous êtes soucieux de performance, comparer donc un code, non simpliste, en ES2015+ et sa traduction ES5 par Babel.
  16. Avatar de danielhagnoul
    • |
    • permalink
    @grunk :
    const et let sont donc des ajouts très intéressant au langages, mais ne remplaceront pas var
    Je vous assure que var est la cause de bien des problèmes (par exemple : la portée globale, la déclaration de paramètre après usage dans une fonction, la perte de la valeur d'un paramètre dans une boucle). La portée bloc est un plus indéniable, car elle impose plus de rigueur et permet de concevoir des arrangements de code impossible autrement.

    J'ai eu le cas récemment avec IE10 et 11 qui sont supposé être compatible ES2015
    Non compatible ! Obsolète ! Abandonné par Microsoft : https://www.microsoft.com/fr-fr/wind...-of-ie-support

    Pour ce qui est de la compatibilité , comment on fait avec tous les sites écrit en js non moderne ? Du jour au lendemain on condamne des millions de sites ? Plein de petits sites sont en ligne , utiles mais non maintenu pour X raisons.
    Avec la première solution : il suffirait d'indiquer au navigateur d'utiliser la version JS adéquate.
    Avec la seconde solution : il suffit de ne pas utiliser l'instruction "use strict".

    La seul contrainte que ça apporte c'est éventuellement de freiner l'adoption des nouvelles versions (on change pas quelque chose qui marche).
    Cette réflexion illustre mon propos, c'est un signe indéniable de la maladie de JS.
  17. Avatar de Namica
    • |
    • permalink
    Je propose deux solutions :
    1. Donner un numéro de version à JS, avec un grand ménage sur les instructions qui existaient avant ES2015.
    2. Réviser le contenu de l'instruction "use strict" dans le sens ci-dessus et promouvoir largement son usage.
    Belle idée, mais quel système de version ? Celui de I.E., de Firefox, de Chrome, autre... ? Et ça ne résout pas le problème des sites anciens.
  18. Avatar de SylvainPV
    • |
    • permalink
    Il existe une solution pour distinguer les environnements "modernes" des dépassés, et utiliser directement du JS moderne tout en préservant la compatibilité grâce à Babel et aux polyfills: <script type="module"> et <script nomodule>. C'est ce que propose le framework Vue.js avec son option Modern Build: https://cli.vuejs.org/guide/browser-...ml#modern-mode
  19. Avatar de Grulim
    • |
    • permalink
    2 choses me choquent :
    1) Babel qui produirait du code moisi : Babel transpile le code de façon conforme au proposition du TC39 (cf https://github.com/babel/proposals).
    2) Je produis pas mal de code JS, je dois bien dire que je ne vois plus l'utilité de var (et très peu let).
  20. Avatar de lmontout
    • |
    • permalink
    C'est au niveau de ton éditeur de code de te suggérer des évolutions de codes pertinents.
    J'aime bien les outils (langage, edi, progiciel etc....) qui me garantissent de bien fonctionner à chaque montée de version sans passer des mois à lire les "breaking changes" et à imaginer les patch.
Page 1 sur 2 12 DernièreDernière