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

JavaScript Discussion :

[Ludique] Défis code en un tweet


Sujet :

JavaScript

  1. #441
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 890
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 890
    Points : 3 729
    Points
    3 729
    Par défaut
    Citation Envoyé par Watilin Voir le message
    Moi ce qui m’intéressait c’est le processus de remontée de parent en parent. Cette conversation avec patricktoulon m’a rappelé que ce n’est pas quelque chose de complètement trivial. Et encore moins quand on est limité en espace…

    Mais en tout cas, merci pour ta solution que je ne connaissais pas
    J'avais pensé à ça quand j'ai lu ton message mais j'ai lu que c'était un moyen répandu mais qui ne fonctionne pas toujours correctement en plus d'être plus long. Je crois que le problème c'est quand il y a des bordures...

    Et ce qui était conseillé c'est d'utiliser la fonction que Sylvain a utilisée...

  2. #442
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 890
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 890
    Points : 3 729
    Points
    3 729
    Par défaut
    Voici un des passages que j'avais lu :

    Finding an Element's Location Relative to the Page Origin

    An element has convenient CSSOM properties to find its location relative to the element's offsetParent or the viewport. There is currently no CSSOM property to directly locate an element based on the page (document) origin (for instance, similar to the pageX/pageY properties for mouse events).
    A common solution to find the element's location relative to the page involves summing the value of offsetTop with the element's offsetParent.offsetTop and so on until offsetParent returns null. (Naturally, offsetLeft is used for horizontal positioning.) Avoid this practice for the following reasons:

    1. The offsetTop value does not include the width of the offsetParent's border. This can lead to slight misalignments when any element in the offsetParent chain has a border style applied.
    2. These repeated summations can contribute to slow performance when offsetParent chains are long.

    With Internet Explorer 9, it is better to use the newly added window.pageYOffset property (window.pageXOffset for horizontal scenarios). The recommended practice to find an element's vertical location from the page's origin is to add the element's getBoundingClientRect().top property to the window.pageYOffset value. (getBoundingClientRect().left + window.pageXOffset for the horizontal location.) This yields the correct result avoiding both pitfalls previously shown.
    Source : https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

  3. #443
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    il faut utiliser yield
    Le jour où un générateur s’avérera utile au golfing, j'ouvre un cabinet dentaire à côté du poulailler.

    En remontant la chaîne des offsetParent, j'ai 38 caractères: f=e=>e?e.offsetTop+f(e.offsetParent):0

    Mais cette méthode est plus longue et moins précise que la première.

  4. #444
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Je profite du up de ce topic pour mettre un lien vers un défi de code golfing lancé par un mec de Mozilla, auquel j'ai participé récemment : https://people.mozilla.org/~fbraun/f...ngerprint.html
    On s'est un peu embrouillés sur les règles mais le problème reste intéressant et utile

  5. #445
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Citation Envoyé par SylvainPV Voir le message
    Le jour où un générateur s’avérera utile au golfing, j'ouvre un cabinet dentaire à côté du poulailler.
    Justement, c’était un peu le but

    En remontant la chaîne des offsetParent, j'ai 38 caractères: f=e=>e?e.offsetTop+f(e.offsetParent):0
    … Eeet la récursivité. J’avais oublié ça aussi. Décidément, je suis pas en forme aujourd’hui.

    Allez je vous livre en pâture le bout de code dont j’étais fier il y a quelques heures.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ($,g=function*($){while($)yield $.offsetTop,$=$.offsetParent})=>[for(o of g($))o].reduce((s,o)=>s+o)
    En version non minifiée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (elem, generator = function* (el) {
        while (el)
          yield el.offsetTop,
          el = el.offsetParent
      }) => [for (offset of generator(elem)) offset]
        .reduce((sum, offset) => sum + offset);
    Peut-être qu’on peut quand même y piocher des idées qui auront un usage quelconque

  6. #446
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    C'est la dure loi du golfing, le chemin le plus court est rarement le plus élégant

    http://i.imgur.com/bDW7DCG.gifv

  7. #447
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Allez, en effet, ça fait longtemps... vais donc vous donner de quoi vous amuser un peu

    Je voudrais avoir une fonction permettant de récupérer le résultat d'un nombre indéfini d'opérations asynchrones (nécessitant un callback), sans déclarer de callback et avoir les différents traitements dans le même scope, un peu comme si on avait le support du async.

    Exemple:

    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
    void function() {
        var
        readFile,
        writeFile,
        FILE1_PATH,
        FILE2_PATH;
     
        readFile = require('fs').readFile;
        writeFile= require('fs').writeFile;
     
        FILE1_PATH = __filename;
        FILE2_PATH = __filename + 2;
     
        ... = fn(readFile, FILE1_PATH, ...);
        ... = fn(writeFile, FILE2_PATH, FILE1_DATA, ...);
        // etc.
    }();
    Attention, ce n'est qu'un exemple, la structure de votre code d'usage n'a pas forcément à ressembler à cela, tant que toutes les instructions sont dans le même scope

    Votre code doit être valide ES2015... et, perso, ma solution ne fait que 114 caractères ^^

    Bon amusement


    PS: J'en ferai sans doute un micro NPM

  8. #448
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    @Lcf: sans yield devant les appels je ne vois pas comment ce que tu demandes est possible; Vous êtes vraiment décidés à utiliser les générateurs hein

  9. #449
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    @Sylvain: Je n'ai pas dit qu'on ne pouvait pas

    Après, c'est pas un beau défi quand même? Sais pas pour vous, mais j'trouve qu'avec si peu de code, pouvoir "redresser" une suite d'opérations asynchrones, c'est plutôt cool et utile.

  10. #450
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Tu n'en avais pas mis dans ton code d'exemple, c'est ça qui m'a surpris.

    Les amis, j'apprécie le up de ce bon vieux topic mais pour vos propositions d'exercice, pouvez-vous fournir un code d'exemple complet avec une fonction F identifiée à implémenter, et quelques tests avec les résultats attendus ? C'est plus simple pour comprendre l'exercice et on perd moins temps à débattre de qu'est-ce que doit faire la fonction, et non pas comment l'implémenter.

  11. #451
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Ok, désolé, voici donc ce qui doit pouvoir tourner :

    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
    f(function*(callback) {
        var
        readFile,
        writeFile,
        error,
        data;
     
        readFile = require('fs').readFile;
        writeFile = require('fs').writeFile;
     
        [error, data] = yield readFile(__filename, callback);
     
        if (error) {
            throw error;
        }
     
        [error] = yield writeFile(__filename + '2', data, callback);
     
        if (error) {
            throw error;
        }
     
        console.log('done');
    });

    EDIT : J'ai une solution en 37 caractères

  12. #452
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Bon ça ne répond pas à toutes mes questions... Je comprends bien que ce que tu nous demandes est de faire une fonction d'éxécution de coroutine, l'exemple classique qui revient dans tous les tutos sur les générateurs. Mais il en existe une multitude d'implémentations avec toutes sortes de caractéristiques sur le traitement des retours, la gestion des exceptions, des timeouts... un peu comme du temps des Promise avec bluebird, Q et compagnie. Or tu n'as posé presque aucune contrainte sur l'implémentation, donc ça rend l'exercice un peu trop facile.


    Je vois qu'il y a cet argument callback qui a fait son apparition. Je suppose donc que les fonctions asynchrones appellent ce callback lorsqu'elles se terminent. C'est un choix arbitraire, on pourrait très bien passer par des Promise par exemple.


    J'ai essayé de reproduire un code de test basique qui suive tes indications et ne requiert pas Node afin que l'on puisse tester facilement sur navigateur en F12.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    f(function*(callback) {  var x = 0;
     
      yield setTimeout(() => { x++; callback() }, 10);
      yield setTimeout(() => { x++; callback() }, 20);
      yield setTimeout(() => { x++; callback() }, 30);
     
      console.log(x, x === 3);
    });

    Dans ce cas l'implémentation la plus courte que j'ai est: f=G=>{g=G(_=()=>g.next());_()} (28 caractères)


    Il faudrait préciser ou complexifier l'exercice parce qu'en l'état j'ai l'impression que c'est un cas d'utilisation basique des générateurs, avec un peu trop de degrés de liberté.

  13. #453
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Hum, oui mais non... ta solution ne fonctionne pas avec mon exemple car, en effet, ta fonction ne récupère pas les valeurs envoyées au callback, afin d'en faire ce qu'on veut ensuite.

    Pourtant, ta solution n'est pas très loin de la mienne... (au passage, suis arrivé à 35 caractères)

    Le but n'est pas de faire un truc super complexe mais juste que ça marche, avec le moins de code possible... pour ça qu'il n'y a pas des masses de contraintes

  14. #454
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    "juste que ça marche", je veux bien mais encore faut-il savoir précisément quelles sont les contraintes attendues. C'est ça que je demande depuis le début

    Alors ajoutons la gestion des valeurs de retour aux contraintes. Toujours en 28: f=G=>{g=G(_=r=>g.next(r));_()}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    f=G=>{g=G(_=r=>g.next(r));_()}
     
    f(function*(callback) { 
      var x = 0;
     
      x += yield setTimeout(() => callback(1) , 10);
      x += yield setTimeout(() => callback(1) , 20);
      x += yield setTimeout(() => callback(1) , 30);
     
      console.log(x, x === 3);
    });
    Si la valeur de retour ne doit pas être le premier argument du callback mais une array des arguments passés, comme semble l'indiquer ton exemple, alors j'arrive à 33: f=G=>{g=G(_=(...r)=>g.next(r));_()}

  15. #455
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Ben, il faut pouvoir récupérer TOUS les paramètres passés au callback, sinon, ça peut pas marcher, avec des callbacks comme on les a sous node, par exemple.

    Exemple, à partir de ton bout de code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    f(function*(callback) { 
      var results = [];
     
      results[0] = yield setTimeout(callback, 10, 0, 'a');
      results[1] = yield setTimeout(callback, 20, 1, 'b');
      results[2] = yield setTimeout(callback, 30, 2, 'c');
     
      console.log(results); // [ [ 0, 'a' ], [ 1, 'b' ], [ 2, 'c' ] ]
    });

  16. #456
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Okay donc 33 pour moi, cf ma dernière phrase. Je ne trouve pas ça très intuitif de retourner une Array, surtout quand on à l'habitude des Promise.

  17. #457
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Super bien joué... moi, j'avais ceci : f = (c,n=(...a)=>g.next(a),g=c(n))=>n();
    Citation Envoyé par SylvainPV Voir le message
    Je ne trouve pas ça très intuitif de retourner une Array, surtout quand on à l'habitude des Promise.
    Perso, j'trouve pas ça super dérangeant, au contraire même, tu les as dans l'ordre dans lequel le callback normal les recevrait... pas spécialement déstabilisant, quoi ^^

  18. #458
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Allez pour maintenir le rythme et occuper le dimanche, je lance un nouvel exo pas trop compliqué ^^

    Une fonction qui inverse majuscules et minuscules dans une phrase. Tests à valider:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    console.assert( f("Hello WoRlD !") === "hELLO wOrLd !");
    console.assert( f("mozzarella") === "MOZZARELLA");
    console.assert( f("GORGONZOLA") === "gorgonzola");

  19. #459
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    59? s=>s.replace(/./g,c=>c>'`'?c.toUpperCase():c.toLowerCase())

    @SylvainPV : Tiens, dans ta solution à mon défi, fais gaffe que ton g pollue l'espace global

  20. #460
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Joli J'ai cherché des pistes plus compliquées et j'étais pas tombé en dessous des 65:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    f=s=>[...s.toLowerCase()].map((c,i)=>c==s[i]?c.toUpperCase():c).join('')
     
    f=s=>s.toUpperCase(i=0).replace(/./g,c=>c==s[i++]?c.toLowerCase():c)
     
    f=s=>s.replace(/([A-Z])|./g,(l,C)=>l[`to${C?"Low":"Upp"}erCase`]())
    En combinant nos techniques, on arrive à 57:

    f=s=>s.replace(/./g,c=>c[`to${c<'`'?"Low":"Upp"}erCase`]())

    On s'autorise les variables globales depuis le début de ce topic, c'est pas nouveau.

Discussions similaires

  1. Défi : Toutes les semaines un peu de code pour aller plus loin avec Windows 7
    Par Jérôme Lambert dans le forum Développement Windows
    Réponses: 41
    Dernier message: 05/01/2012, 12h00
  2. [Ludique] Mini-jeu : épisode 3 (déchiffrage de code, niveau : facile)
    Par RomainVALERI dans le forum Général JavaScript
    Réponses: 17
    Dernier message: 03/11/2010, 00h45
  3. [Ludique] Mini-jeu - niveau 2 : déchiffrage de code (niveau modéré)
    Par RomainVALERI dans le forum Général JavaScript
    Réponses: 13
    Dernier message: 28/07/2010, 23h15
  4. [Ludique] Mini-jeu : déchiffrage de code (niveau facile)
    Par RomainVALERI dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 13/07/2010, 18h24

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