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

Langage Perl Discussion :

fonction rand sur un tableau ?


Sujet :

Langage Perl

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut fonction rand sur un tableau ?
    Bonsoir,

    voilà j'ai un tableau à 1 dimension, et j'aimerais sortir une de ces valeurs au hasard, j'ai trouvé un vieux post mais il ne marche hélàs pas.

    Le tableau est au début du fichier et l'appel du 'rand' dans une procédure (ça ne doit pas impliquer d'erreur ça si ?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    my @tab = ("Super", "Cool", "Content", "Test", "Etc...");
     
    $tab[rand ($#tab + 1)];

    Comment peut-on faire un rand sur un tableau ?

    Je vous remercie d'avance de l'aide que vous pourrez m'apporter

  2. #2
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    En quoi ça ne marche pas ? Ce code marche parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my @tab = ("Super", "Cool", "Content", "Test", "Etc...");
    print $tab[rand ($#tab + 1)];
    Bien que personnellement, j'aurais plutôt tendance à écrire :
    (ça fait exactement la même chose, c'est juste un peu moins lourd)

    --
    Jedaï

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Comme je disais avant d'être déconnecté ( :/ ) c'est que cette commande ne marchait pas lorsqu'elle était appliquée pour être renvoyée sur le chan. En bidouillant un peu je me suis aperçu qu'il suffisait 'bêtement' d'allouer la commande à une variable (test que j'avais fait une fois mais qui avait bugué sûrement dû à une erreur de ma part ).
    Ca donne donc ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    my @tab = ("Super", "Cool", "Content", "Test", "Etc...");
     
    #Dans la procédure
    my $rand = $tab[rand @tab];
    $self->privmsg($chan, $rand);   #équivalent du print pour irc
    Voilà mais j'ai une autre question à ce propos, peut-on faire en sorte que ce qui sort ne peut pas ressortir lors de l'appel de la commande ?

    Ex: $rand donne Cool et lors des appels suivants cela ne donne pas de nouveau Cool ?

    Merci

  4. #4
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Citation Envoyé par Kyp_Durron Voir le message
    Voilà mais j'ai une autre question à ce propos, peut-on faire en sorte que ce qui sort ne peut pas ressortir lors de l'appel de la commande ?

    Ex: $rand donne Cool et lors des appels suivants cela ne donne pas de nouveau Cool ?
    Oui, on peut.

    Hein ? Comment ? Ah, euh, en fait il y a vraiment l'embarras du choix.
    En utilisant les valeurs du tableau comme clés d'un tableau associatif avec pour valeur un marqueur indiquant s'il peut être utilisé ou pas et s'il ne peut pas, on relance (alambiqué et inefficace).
    Ou comme clés d'un tableau associatif à valeurs quelconques, en éliminant l'élément qui vient de sortir (un poil alambiqué aussi).
    Ou alors, en retirant du tableau (ou d'une copie) la valeur qui vient de sortir au moyen de l'opérateur splice (bien mieux, déjà).
    Ou encore, en mélangeant le tableau à l'avance avec un truc genre @shuffled = sort {int (rand 2) * 2 - 1} @tab;, puis en parcourant séquentiellement la version mélangée. Cette dernière solution-ci à ma préférence, mais c'est très subjectif : je n'ai aucun argument objectif pour la préférer à la précédente, si ce n'est peut-être qu'elle est également très pratique pour mélanger un paquet de cartes, ou équivalent.

    Il y a certainement plein d'autres solutions.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    J'aurais pu penser au splice oui, je vais aller m'acheter des pensées perl
    Je vais tenter le tout :o) Par contre, peux-tu m'éclairer sur le:
    (rand 2) * 2 - 1 ?

    Merci bien

  6. #6
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Oui, ça peut paraître un peu étrange de prime abord. Ça vient de la façon de fonctionner de l'opérateur(*) sort : il attend soit +1, soit 0, soit -1, et en fonction de ça il intervertit ou non les éléments évalués. Partant du principe que si le résultat de la fonction de comparaison est 0, sort s'abstient de toute interversion, pour bien bordéliser mon mélange (ce qui est quand même le but de la manoeuvre), j'ai préféré éliminer la possibilité que le résultat soit 0 (sinon il n'y avait qu'une chance sur trois d'inversion, si j'ai bien compris). D'où le int (rand 2) * 2 - 1 (**), qui vaut soit 1 soit -1, aussi aléatoirement que le permet la fonction rand.

    (*) Ou fonction native si vous préfèrez.
    (**) Ne pas oublier le int, il est important.

  7. #7
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Plutôt que ce shuffle très bricole, je te conseille plutôt d'utiliser le shuffle() de List::Util (qui est dans le CORE) qui utilise l'algorithme de Fisher-Yates (garantit l'équiprobabilité des distributions) et est implémenté en C pour la vitesse.

    --
    Jedaï

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    J'ai regardé la doc pour voir comment marcher le shuffle() de List::Util mais le prog bug.

    De ce que j'ai compris le shuffle marche ainsi (et donc mon random précédent devient inutile).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    use List::Util qw(shuffle); #qw(shuffle) vraiment utile ?
     
    my @cartes = ("As de carreau", "Roi de pic", "Dame de coeur", "Valet de trèfle");
     
    @cartes = shuffle 0..3;
    Seulement après, pour faire le renvoi sur la console il faut faire print sur quoi ? Ne sachant pas j'ai testé ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    use List::Util qw(shuffle); #qw(shuffle) vraiment utile ?
     
    my @cartes = ("As de carreau", "Roi de pic", "Dame de coeur", "Valet de trèfle");
     
    my $test = (@cartes = shuffle 0..3);
    print $test;
    Cependant cela ne marche pas Puissiez-vous m'éclairer sur mon erreur ?

    Merci

  9. #9
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    Tu affectes un tableau à une variable scalaire. Le tableau est donc évalué en contexte scalaire, ce qui fait que $test reçoit le nombre d'éléments du tableau, donc 4. Documente-toi sur les contextes (notemment), c'est très important pour maîtriser Perl, et j'ai l'impression que tu as de grosses lacunes sur cet aspect du langage.

    Quant à savoir comment imprimer ton résultat, ben, si c'est juste pour un test, tu peux te contenter d'un print "@cartes\n" ; qui va bien. Ou, pour une meilleure lisibilité sur la console, print join "," , @cartes;

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Il est vrai que j'ai quelques lacunes et c'est dû en partie à la formation en perl que j'ai eu...je tâtonne donc pour les contextes.

    Cependant j'ai un problème qui vient du List::Util qw(shuffle); ou alors du @cartes = shuffle 0..3; Je ne comprends pas étant donné que ces deux lignes sont normalement justes...

  11. #11
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Kyp_Durron Voir le message
    Il est vrai que j'ai quelques lacunes et c'est dû en partie à la formation en perl que j'ai eu...je tâtonne donc pour les contextes.

    Cependant j'ai un problème qui vient du List::Util qw(shuffle); ou alors du @cartes = shuffle 0..3; Je ne comprends pas étant donné que ces deux lignes sont normalement justes...
    Ca m'amuse toujours quand les gens me disent que leur code qui ne marche pas est "normalement juste"...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    use List::Util qw(shuffle);
     
    my @cartes = shuffle ("As de carreau", "Roi de pic", "Dame de coeur", "Valet de trèfle");
    --
    Jedaï

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Et bien content de te faire rire (je suis meilleur à ça qu'au perl :/)
    Erreur d'interprétation de ma part :/

    Il y a néanmoins un problème (encore et toujours ), le bot tique sur le use List::Util qw(shuffle);

    Cela pourrait-il venir de ma version de perl ?


    Merci bien pour l'aide :]

  13. #13
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    C'est possible si tu as un Perl 5.6. Note bien que Perl5.8 est sorti il y a plus de 5 ans maintenant... Pour une version en pur Perl de shuffle(), tu peux lire ce vieux sujet. Si tu peux, le mieux reste d'installer List::Util sur ton vieux Perl, voire de mettre ton Perl à jour.

    --
    Jedaï

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Merci bien :] En effet j'ai pas la 5.8 et je vais la dl de suite ça sera plus simple pour la suite

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Hmm j'ai installé la version 5.8 de Perl et également regardé le le vieux post. Si j'ai tout compris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #devrait marcher
    use List::Util qw(shuffle);
     
    my @cartes=("As","Roi","Dame","Valet");
    @cartes = shuffle @cartes;
    foreach my $test (@cartes) {
      print "$test\n";
    }
    Mais ça marche pas

  16. #16
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Kyp_Durron Voir le message
    Mais ça marche pas
    Décris un peu ce que tu veux dire par "ça ne marche pas" !! Chez moi ce code marche très bien.

    --
    Jedaï

  17. #17
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Hum, désolé quand je ne mets que ça comme code cela marche très bien en effet. Je l'ai essayé avec le reste et ça marche aussi, j'avais mis un $ au mauvais endroit.

    Désolé d'avoir été en mode boulet :/ (la console s'ouvrant et se fermant illico je n'avais pu voir quelle erreur il me mettait).

    Merci pour tout :]

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

Discussions similaires

  1. fonction rand() sur chaine de caracteres
    Par ellgafsi dans le forum Langage
    Réponses: 17
    Dernier message: 03/06/2009, 16h44
  2. Réponses: 2
    Dernier message: 21/10/2008, 20h59
  3. Réponses: 3
    Dernier message: 19/11/2007, 19h36
  4. rand sur un tableau
    Par MaitrePylos dans le forum Ruby on Rails
    Réponses: 2
    Dernier message: 22/03/2007, 10h54
  5. fonction rand() sur liste ?
    Par debutant-1 dans le forum C
    Réponses: 10
    Dernier message: 24/05/2006, 10h58

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