fonction rand sur un tableau

Eléphanteau du PHP | 10 Messages

07 oct. 2008, 22:49

Bonjour,

J'avais fait développer un script il y a environs 1 an par un programmeur, que je n'arrive plus à joindre. :twisted:

Le script génère du texte aléatoirement.

Je souhaite maintenant faire évoluer ce script, et faire en sorte, que des mots prédéfinis dans un tableau (variable $motfixe) soit inséré au hasard dans le texte généré.

Je n'arrive pas a comprendre ce que cette personne a fait comme code au niveau "generation du code" et ne sais donc pas ou insérer $tableau[$motfixe[0]] pour qu'un des mots contenu dans l'array soit insérer par exemple 10 fois dans tout le texte...

Pourriez vous m'aider svp? :roll:

Merci beaucoup! :)
<?php

$nbremots= rand(200, 500);

for ($sa=0;$sa<$nbremots;$sa++) 
{
// definition de la taille d'un mot
$taille = rand(1, 12);

//mots fixe
$tableau = array('gagne', 'perdu', 'rejouer');
$motfixe = array_rand($tableau, 2);

//tableau des consonnes
$consonne = array('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z', 'dd', 'ff', 'll', 'mm', 'nn', 'pp', 'rr', 'ss', 'tt');

//tableau des voyelles. certaines voyelles ont été doublées ou triplé, comme le a ou le e, car elles sont tres repandu, contrairement au y
$voyelles = array('a', 'a', 'a', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u', 'u', 'y');
    
$code="";

//generation du code
for ($i=1;$i<$taille;$i++) 
$code .= ($i%2==0)?$consonne[rand(0, count($consonne)-1)]:$voyelle[rand(0, count($voyelle)-1)];
   
echo ''.$code.' '.$tableau[$motfixe[0]].' ';
}
?>

ViPHP
ViPHP | 4674 Messages

08 oct. 2008, 00:27

Hey :),

Je te conseille d'oublier ce code pour l'instant et d'écrire ton propre algorithme. Tu apprendras, tu feras quelque chose de propre et tu seras tout content. Comment est-ce que tu procéderais :) ? Je t'écoute.


PS : le code que tu nous as fournit est assez mauvais soit dit en passant, d'où mes propos.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 10 Messages

08 oct. 2008, 09:38

Bonjour,

Aie ok!

Bon même si je ne suis pas super bon en programmation, je vais essayer...mais pourriez vous me guider sur la solution à choisir?

D'après mes recherches, je pourrais soit réutiliser les array avec les consonnes et voyelles, mais en appliquant un array_rand dessus.

Soit je laisse tomber les tableaux et je liste les lettres de l'alphabet avec:
<?php //On liste les lettres de l'alphabet
foreach(range('a', 'z') as $lettre)
{
echo"$lettre ";
}
?>
Quelle est la meilleure solution?

EDIT: J'ai commancé en optant pour les tableaux:
<?php

$nbremots= rand(200, 500);

for ($sa=0;$sa<$nbremots;$sa++) 
{
// definition de la taille d'un mot
$taille = rand(1, 12);

//mots fixe
//$tableau = array('jeux', 'jeux en ligne', 'jeux gratuits');
//$motfixe = array_rand($tableau, 2);

//tableau des consonnes
$tableau2 = array('b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z', 'dd', 'ff', 'll', 'mm', 'nn', 'pp', 'rr', 'ss', 'tt');
$consonne = array_rand($tableau2, 2);

//tableau des voyelles. certaines voyelles ont été doublées ou triplé, comme le a ou le e, car elles sont tres repandu, contrairement au y
$tableau3 = array('a', 'a', 'a', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'u', 'u', 'y');
$voyelles = array_rand($tableau3, 2);

$code="";

//generation du code
for ($i=1;$i<$taille;$i++) 
$code .=  ''.$tableau2[$consonne[0]].''.$tableau3[$voyelles[0]].'';
   
echo ''.$code.' ';
}

 ?>
Mais cela me génère quasiment toujours les mêmes mots, à savoir "hahahaha" "hihihihi" "lololo"

C'est un peu normal car je demande de choisir une fois une consonne, puis une voyelle, puis une consonne...

Comment randomiser également la structure du mot?

merci[/php]

Eléphant du PHP | 422 Messages

08 oct. 2008, 11:51

Quelque chose qui peut t'aider :
http://pear.php.net/package/Text_Password

Un générateur de mots de passe (donc de mots) prononçables ou imprononçables.

Eléphanteau du PHP | 10 Messages

08 oct. 2008, 12:12

Merci mais j'ai réussi à faire le générateur de mots!! \:D/
<?php
$nbrelettre = rand(2, 10);

for ($sa=0;$sa<$nbrelettre;$sa++) 
{
//On liste les lettres de l'alphabet dans la variable $lettres
$lettres = range('a', 'z');
$motgenere = $lettres[array_rand($lettres)];

//Affiche un mot imaginaire comprenant entre 2 et 10 lettres.
echo $motgenere;

} ?>
C'est bien comme ca ou ce code n'est il pas "propre"?

Par contre, le code ci-dessus ne génère qu'un seul mot et je souhaiterai générer un texte. J'ai donc pensé faire comme ci-dessous, par contre cela ne semble pas fonctionner car cela m'affiche a chaque fois qu'une lettre et non le mot!
$nbrelettre = rand(2, 20);
$nbremots = rand(50, 100);
for ($sa=0;$sa<$nbrelettre;$sa++) 
{
//On liste les lettres de l'alphabet dans la variable $lettres
$lettres = range('a', 'z');
$motgenere = $lettres[array_rand($lettres)];

  for ($mot=0;$mot<$nbremots;$mot++) 
    {
   //Répète x fois (selon $nbremots) le mot imaginaire qui a été généré.
   echo "$motgenere ";
    }
}
Merci

Mammouth du PHP | 1353 Messages

08 oct. 2008, 13:42

Bonjour,

C'est normal, à chaque itération tu écrases la valeur de $motgenere par la nouvelle lettre...

Il faut utiliser la concaténation avec le .= , du genre :
$nbrelettre = rand(2, 20); 
$nbremots = rand(50, 100); 
$motgenere = "";
for ($sa=0;$sa<$nbrelettre;$sa++)  
{ 
//On liste les lettres de l'alphabet dans la variable $lettres 
$lettres = range('a', 'z'); 
$motgenere .= $lettres[array_rand($lettres)]; 
}
Aussi sort le echo de ta premiere boucle for sinon il va le répéter au fur et a mesure de la construction du mot généré...
Tell me and I forget. Teach me and I remember. Involve me and I learn.

ViPHP
ViPHP | 4674 Messages

08 oct. 2008, 13:55

Bon même si je ne suis pas super bon en programmation, je vais essayer...mais pourriez vous me guider sur la solution à choisir?
Bien sûr ! Je disais ça pour te faire réfléchir et te faire prendre conscience que le problème est très simple. Et bien sûr, si tu apportes des solutions, on s'aura les évaluer et t'éclairer, c'est naturel, on est là pour ça :). On encourage toujours ceux qui font des efforts.

Tu as donc trouvé la solution suivante :
$nbrelettre = rand(2, 10); 

for ($sa=0;$sa<$nbrelettre;$sa++)  
{ 
    //On liste les lettres de l'alphabet dans la variable $lettres 
    $lettres = range('a', 'z'); 
    $motgenere = $lettres[array_rand($lettres)]; 

    //Affiche un mot imaginaire comprenant entre 2 et 10 lettres. 
    echo $motgenere; 
}
C'est pas mal, sauf une chose. Ici, ton tableau $lettres est toujours le même (il contient toujours l'alphabet latin). Donc, rien ne sert de le placer dans la boucle. S'il est un niveau plus haut, il sera forcément accessible dans la boucle. On aurait donc (avec quelques optimisations) :
$alpha = range('a', 'z');
$word  = null;

for($i = 0, $length = rand(2, 10); $i < $length; $i++)
    $word .= $alpha[array_rand($alpha)];

var_dump($word);
Ici, tu vois que j'ai sorti notre alphabet ($alpha). J'ai initialisé un mot vide (epsilon en théorie des langages), soit un mot nul. Ensuite, on fait une boucle. Dans cette boucle, on initialise plusieurs variables : notre variable incrémentée $i, et la longueur de notre mot $length. On teste ensuite pour $i < $length.
Pour chaque lettre donc, on la concatène avec le mot. On va donc construire un mot.

Tu vois que la boucle fait un traitement minimal. Toutes les autres données sont déclarées en dehors. Il faut absolument sortir ce qui est sortable de la boucle. Là tu effectues entre 2 et 10 traitements, ça ira, mais si tu fais 1000 traitements, c'est déjà autre chose (100 fois plus, eh oui …).

Maintenant, on sait générer un mot. Imagine que tu veuilles générer plusieurs mots : c'est le même procédé. On a toujours notre alphabet, toujours notre longueur de mot aléatoire ; on ne travaille plus sur un mot, mais sur une phrase. Donc :
$alpha    = range('a', 'z');
$language = null;

for($e = 0, $words = rand(5, 23); $e < $words; $e++) {

    for($i = 0, $length = rand(2, 10); $i < $length; $i++)
        $word .= $alpha[array_rand($alpha)];

    $word .= ' ';
}

var_dump($langage);
On va générer ici entre 5 et 23 mots, où chaque mot a une taille comprise entre 2 et 10.

Est-ce que tu comprends :) ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 10 Messages

08 oct. 2008, 14:11

Alors ca fait un peu beaucoup d'un coup mais je crois avoir compris.

D'ailleurs il y avait une erreur dans ton code, pour que cela fonctionne j'ai remplacé la variable langage par word.
<?php
$alpha    = range('a', 'z');

for($e = 0, $words = rand(50, 100); $e < $words; $e++) {

    for($i = 0, $length = rand(2, 10); $i < $length; $i++)
        $word .= $alpha[array_rand($alpha)];

    $word .= ' ';
}

var_dump($word);
?>
Ca fonctionne nickel chrome! Maintenant il me reste a trouver la solution pour intégrer les mots prédéfinis un nombre x de fois à des endroits x.

Je vais commencer a cogité et je ferai un reply :)

Merci encore pour ces explications très instructives!

ViPHP
ViPHP | 4674 Messages

08 oct. 2008, 14:17

Ah oui mince, je suis tête en l'air …
$alpha    = range('a', 'z'); 
$language = null; 

for($e = 0, $words = rand(5, 23); $e < $words; $e++) { 

    for($i = 0, $length = rand(2, 10); $i < $length; $i++) 
        $language .= $alpha[array_rand($alpha)]; 

    $language .= ' '; 
} 

var_dump($language);
Je ne teste pas tous les codes hein ;-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 10 Messages

08 oct. 2008, 15:13

Re ! :D

Alors voila, je suis un peu bloqué...

Voici le code qui génère donc le texte et les mots:
<?php

$alphabet = range('a', 'z'); 
$language = null; 
//On génère entre 100 et 500 mots
for($e = 0, $words = rand(100, 500); $e < $words; $e++) 
{ 
    //Un mot contient entre 2 et 10 caracteres
    for($i = 0, $length = rand(2, 10); $i < $length; $i++)  
        $language .= $alphabet[array_rand($alphabet)]; 

    $language .= ' '; 
} 

echo $language; 
?>
Maintenant, en supposant que je voudrai qu'un mot précis soit introduit à des endroits au hasard dans le texte, en sachant que celui ci doit apparaitre pour l'équivalent de 5% du texte entier... |*()

En gros, voila ce que j'ai fait:
<?php
//Les mots doivent apparaitre x fois dans le texte, x correspondant à 5% du nombre de mots 
$pourcent = $words*0.05;

//mots fixe
$tableau = array('jeux', 'jeux en ligne', 'jeux gratuits');
$motfixe = array_rand($tableau, 2);

echo $tableau[$motfixe[0]];

?>
Cela fonctionne bien, un mot est tiré au hasard du tableau. La variable pourcent contient le nombre de fois que le mot doit apparaitre.

Par contre je cale, ou dois je introduire cette condition et comment? Dans la première ou seconde boucle FOR? Dois je créer une nouvelle boucle? (if? while? for?)

Merci

ViPHP
ViPHP | 4674 Messages

08 oct. 2008, 15:21

Hmm, dans la première boucle, tu auras une condition : si on doit écrire un mot, on l'ajoute, sinon on le génère automatiquement. Pour savoir si on doit écrire un mot, tu utilises les pourcentages d'apparition. Là, plusieurs solutions : soit tu comptes le nombre de mot déjà écrit, et tu en places un à des emplacements fixes. Ou sinon … hmm, tu as vraiment plusieurs solutions. Tu peux t'amuser avec les positions, les modulo, et des fréquences d'apparition, tout dépend de ce que tu veux faire exactement.

Donc dans la première boucle : une condition. Cette condition donne sur un ajout simple de mot, ou sur la boucle de génération de mot.

Allé, je te passe le clavier :).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 10 Messages

08 oct. 2008, 15:45

En fait je souhaite ajouter ces mots à des endroits non prédéfinis, dans le texte généré. Donc à un endroit au hasard, sans pour autant que 2 mots "fixes" puissent se suivre ou précéder.

Voila ce que j'ai fait pour le moment, en ayant cogité sur le sujet toute la journée:
<?php

$alphabet = range('a', 'z'); 
$language = null; 

//On génère entre 100 et 500 mots
for($e = 0, $words = rand(100, 500); $e < $words; $e++) 
{ 
    //Un mot contient entre 2 et 10 caracteres
    for($i = 0, $length = rand(2, 10); $i < $length; $i++)  
        $language .= $alphabet[array_rand($alphabet)]; 

    $language .= ' '; 
} 
$pourcent = round($words*0.05);

echo $language; 

//Génère les mots fixe x fois (correspondant aux 5%)
for($fix = 0; $fix < $pourcent; $fix++) 
{
//mots fixe
$tableau = array('gagné', 'perdu', 'rejouer');
$motfixe = array_rand($tableau, 2);
echo ''.$tableau[$motfixe[0]].' ';
}
?> 
La première partie génère les mots et le texte. La seconde partie génère le nombre adéquat de "mots fixes".

Par contre après je cale vraiment, je ne vois pas où insérer le code de la seconde partie, dans la première, afin que les mots soient ajoutés au texte...

EDIT 5eme fois...:

J'ai essayé également en faisant:
<?php

$alphabet = range('a', 'z'); 
$language = null; 
$texte = null;
$textefinal = null;

//On génère entre 100 et 500 mots
for($e = 0, $words = rand(100, 500); $e < $words; $e++) 
{ 
    //Un mot contient entre 2 et 10 caracteres
    for($i = 0, $length = rand(2, 10); $i < $length; $i++)  
        $language .= $alphabet[array_rand($alphabet)]; 

    $language .= ' '; 
} 
$pourcent = round($words*0.05);

//echo $language; 

//Génère les mots fixe x fois (correspondant aux 5%)
for($fix = 0; $fix < $pourcent; $fix++) 
{
//mots fixe
$tableau = array("<b>soleil</b>", "<b>argent</b>", "<b>partir vacances</b>");
$texte .= $tableau[array_rand($tableau)];
$texte .= ' '; 
}

//On fusionne les 2 textes
$texteEntier = ''.$language.' '.$texte.' ';

//Si ici je fais un echo, cela affiche le texte entier, avec les mots fixes listés à la fin.
//echo "<font color=red>$texteentier</font>";

// On explose l'array pour récupérer les mots
$texteEntier_explode = explode(' ', trim($texteEntier)); 

// On mélange les mots
shuffle($texteEntier_explode); 

// On recoupe chaque mot séparé d'un espace
$texteFinal = implode(' ', $texteEntier_explode); 

echo "<font color=red>$texteFinal</font>";

?>  
Donc cela fonctionne plus ou moins ainsi...Il y a tout de même un problème...

Si je mets en mot fixe un seul mot, comme par exemple "soleil", cela me dispercera bien le mot n'importe où dans le texte. Par contre il y a un problème avec les mots composés comme "partir vacances". En effet, lorsque le script va tout mélanger, il va faire comme si "partir" et "vacances" étaient 2 mots distincts...et je voudrais qu'ils ne constituent qu'un mot.

Exemple:

Cela affiche: nvxdrr setrndzdv partir lgo lpqt gnjf licrbe vacances wmnrv
Et je voudrais que cela affiche: nvxdrr setrndzdv partir vacances lgo lpqt gnjf licrbe wmnrv

RE edit:

Voila j'ai réussi à tout fusionner et a afficher les mots fixes tels quel, mais ils ne sont pas mélangés car ils sont contenus dans un seul $string
<?php
for($fix = 0; $fix < $pourcent; $fix++) 
{
//mots fixe
$tableau = array("<b>soleil</b>", "<b>argent</b>", "<b>partir vacances</b>");
$texte .= $tableau[array_rand($tableau)];
$texte .= ' '; 
}

$tabfinal = array($texte);

// On explose l'array pour récupérer les mots
$texteEntier_explode = explode(' ', trim($language)); 

//On fusionne les 2 tableaux
$list = array_merge($texteEntier_explode, $tabfinal);

// On mélange les mots
shuffle($list); 

// On recoupe chaque mot séparé d'un espace
$texteFinal = implode(' ', $list); 

echo "<font color=red>$texteFinal</font>";

?> 
Bref, après une journée et une nuit de cogitation, j'en suis la... :roll:

J'ai tout de même quelqu'un qui m' a aidé pour la partie mélange, notemment avec la fonction shuffle.

Svp aidez moi! |*()

merci encore...

ViPHP
ViPHP | 4674 Messages

09 oct. 2008, 13:48

Bien, tu t'es cassé la tête maintenant ;-).
Tu n'es pas loin de la solution pourtant.

Imagine que ta phrase est un tableau de mot. Au lieu de concaténer les mots, on les place dans un tableau dynamiquement. Ensuite, on ajoute des mots au tableau (nos mots fixés, donnés), et on mélange le tout avec shuffle() ?

Ainsi, on aurait :
<?php

/**
 * On crée notre alphabet et notre langage.
 * Notre langage est un tableau de mot.
 */
$alpha    = range('a', 'z');
$language = array();

for($e = 0, $words = rand(5, 23); $e < $words; $e++) {

    /**
     * Cette variable contient notre mot (qui sera la
     * concaténation de lettres).
     */
    $handle = null;

    for($i = 0, $length = rand(2, 10); $i < $length; $i++)
        $handle .= $alpha[array_rand($alpha)];

    /**
     * On ajoute notre mot à notre langage.
     */
    $language[] = $handle;
}

/**
 * Nos mots donnés.
 */
$given = array(
    'phpfrance',
    'super',
    'génial',
    'top',
    'déchire'
);

/**
 * On ajoute nos mots à ceux du langage.
  */
$result = array_merge($language, $given);

/**
 * On mélange le tout …
 */
shuffle($result);

/**
 * Et on reconstruit la phrase.
 */
var_dump(implode(' ', $result));
Tu avais tous les éléments en main. L'idée du shuffle() était bonne. En revanche, tu découpais ton langage (ta phrase) en tableau, alors tu pouvais directement le construire sous forme de tableau (et le transformer en chaîne derrière). Cela évite ton problème des mots donnés avec espace.

T'as compris ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 10 Messages

09 oct. 2008, 14:05

Oui je me suis bien cassé la tête :lol:

Par contre ta solution ne fera pas ce que je veux...

Voila le code actuel au dernier stade:
<?php

$alphabet = range('a', 'z'); 
$language = null; 
$texte = null;
$textefinal = null;

//On génère entre 100 et 500 mots
for($e = 0, $words = rand(100, 500); $e < $words; $e++) 
{ 
    //Un mot contient entre 2 et 10 caracteres
    for($i = 0, $length = rand(2, 10); $i < $length; $i++)  
        $language .= $alphabet[array_rand($alphabet)]; 

    $language .= ' '; 
} 
$pourcent = round($words*0.05);

//Génère les mots fixe x fois (correspondant aux 5%)
for($fix = 0; $fix < $pourcent; $fix++) 
{
//mots fixe
$tableau = array("<font color=red><b>soleil</b></font>", "<font color=red><b>argent</b></font>", "<font color=red><b>partir vacances</b></font>");
//$texte .= $tableau[array_rand($tableau)];
//$texte .= ' '; 
}

// On explose l'array pour récupérer les mots
$texteEntier_explode = explode(' ', trim($language)); 

//On fusionne les 2 tableaux
$list = array_merge($texteEntier_explode, $tableau);

// On mélange les mots
shuffle($list); 

// On recoupe chaque mot séparé d'un espace
$texteFinal = implode(' ', $list); 

echo "$texteFinal";

?> 
Ce qui me donne: http://www.voilou.fr/testmot.php

Les mots en rouge sont les "mots fixes". Ils n'apparaissent qu'une seule fois car j'ai commenté les variables $texte que je n'ai pas utilisés. En décommentant, cela ajoutera bien le nombre de mots fixes voulus dans la variable $texte...Par contre je ne sais pas comment intégrer ceux ci dans le texte.

Voila... :roll:

Merci encore.. :D

ViPHP
ViPHP | 3607 Messages

09 oct. 2008, 14:54

Qu'est-ce que tu veux dire par "ta solution ne donnera pas ce que je veux.."? dévellope un peu...