comment générer un suite spécifique de nombres ?

Petit nouveau ! | 9 Messages

05 mars 2022, 04:11

Bonjour,

Je voudrais générer toutes les possibilités uniques de 10 nombres compris 00 à 99, chaque possibilité n'utilisant qu'une seule fois le même chiffre dans les dizaines ou dans les unités.

Par exemple cette possibilité n'est pas bonne : 01 02 14 23 48 51 66 79 81 90 (l'unité 1 et la dizaine 0 sont utilisées plusieurs fois)

Voici un extrait du résultat attendu fait à la main :

00 11 22 33 44 55 66 77 88 99

01 10 22 33 44 55 66 77 88 99

02 10 21 33 44 55 66 77 88 99
02 11 20 33 44 55 66 77 88 99

03 10 21 32 44 55 66 77 88 99
03 10 22 31 44 55 33 77 88 99
03 11 20 32 44 55 66 77 88 99
03 11 22 30 44 55 66 77 88 99
03 12 20 31 44 55 66 77 88 99
03 12 21 30 44 55 66 77 88 99

04 10 21 32 43 55 66 77 88 99
04 10 21 33 42 55 66 77 88 99
04 10 22 31 43 55 66 77 88 99
04 10 22 33 41 55 66 77 88 99
04 10 23 31 42 55 66 77 88 99
04 10 23 32 41 55 66 77 88 99
04 11 20 32 43 55 66 77 88 99
04 11 20 33 42 55 66 77 88 99
04 11 22 33 44 55 66 77 88 99
04 11 22 34 43 55 66 77 88 99
04 11 23 30 42 55 66 77 88 99
04 11 23 32 40 55 66 77 88 99
04 12 20 31 43 55 66 77 88 99
04 12 20 33 41 55 66 77 88 99
04 12 21 30 44 55 66 77 88 99
04 12 21 34 40 55 66 77 88 99
04 12 23 30 41 55 66 77 88 99
04 12 23 31 40 55 66 77 88 99
04 13 20 31 42 55 66 77 88 99
04 13 20 32 41 55 66 77 88 99
04 13 21 30 42 55 66 77 88 99
04 13 21 32 40 55 66 77 88 99
04 13 22 30 41 55 66 77 88 99
04 13 22 31 40 55 66 77 88 99

etc.

Je pense qu'il faudrait une fonction récursive, mais je n'arrive pas à la structurer.
Je m'y perds aussi avec le contrôle des chiffres déjà utilisés.

Merci de votre attention et pour vos orientations, suggestions ou proposions de code.

Mammouth du PHP | 2703 Messages

05 mars 2022, 15:23

une solution : générer toutes les combinaisons de 10 * 2 chiffres, et ensuite, éliminer toutes les entrées qui ne respectent pas les conditions voulues. il restera alors ce qui est souhaité.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

05 mars 2022, 18:24

Avec une boucle for() de 0 à 99999999999999999999, tu peux générer toutes les combinaisons possibles.
Et à l'intérieur de cette boucle for(), tu peux faire ton analyse pour vérifier si les critères sont respectés. Si c'est le cas tu conserves ce nombre, sinon tu passes au suivant.

Pour vérifier les conditions, je ferrai un tableau des chiffres en position impaire (les unités) et un tableau avec les nombres en position paire (les dizaines), puis je verifierai qu'il n'y a pas des doublons dans chacun des tableaux.
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 9 Messages

05 mars 2022, 21:52

Bonsoir,
Merci à vous 2 pour vos réponses.

Ca me semble être fort gourmand en ressource que de générer toutes les solutions puis de les tester une à une.

Générer un nombre de 00 00 00 00 00 00 00 00 00 à 99 99 99 99 99 99 99 99 99 99 et de le garder que s'il correspond, me parait plus léger, c'est quelle type de variable pour un tel nombre ?
A moins de travailler sur une chaine de 20 caractères.

Dans un cas comme dans l'autre, je coince sur le mode de validation ou de filtrage du "nombre".

est-ce qu'une REGEX pourrait le faire ?

Mammouth du PHP | 2703 Messages

06 mars 2022, 00:12

il faut travailler avec des tableaux.
un tableau de 10 pour le 1er chiffre. un tableau de 10 pour le second et https://www.php.net/manual/fr/function. ... values.php ou https://www.php.net/manual/fr/function.array-unique.php

Petit nouveau ! | 9 Messages

06 mars 2022, 11:52

J'ai utilisé in_array() , mais c'est à quel moment que je dois réinitialiser les 2 tableaux (dizaine et unité) ?

Avatar du membre
Mammouth du PHP | 1609 Messages

08 mars 2022, 14:43

Salut à tous,

Si je ne m'abuse une simple boucle for ne peut pas fonctionner étant donné que la valeur maximum d'un integer php est 2,147,483,647 en 32-bit et de 9.2×10^18 en 64-bit. Hors la on est sur du 1x10^20 - 1 si je dis pas de connerie.
Développeur web depuis + de 20 ans

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

08 mars 2022, 17:46

Exact, bien vu !
L'entier le plus grand que gère PHP en 64 bits est 9 223 372 036 854 775 807.

Du coup, notre approche avec une seule boucle for() n'est pas bonne pour la génération de toutes les possibilités.
En revanche, elle est bonne pour faire la vérification des critères vu qu'on l'exploite comme un string, donc ça ne pose pas de problème sur ce dernier point.
On pourrait concaténer 2 int dans un string afin que ça passe...


Il existe aussi très certainement une solution plus efficace que de tester toutes les possibilités... peut-être en construisant chaque couple de nombre l'un après l'autre, car par exemple si on a déjà éliminé le fait que tous les nombres qui commencent par 00 0... seront invalides, ça ne sert à rien de générer les millions de millions de possibilités qui débutent comme ça pour les invalider ensuite...
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Mammouth du PHP | 1609 Messages

08 mars 2022, 18:55

Je pense qu'il y a un truc à faire en partant du principe qu'il y a 100 "numéros" de 00 à 99 et qu'il y a 10 groupes de numéros, ceux commençant par 0, ceux commençant par 1, ceux commençant par 2, etc car lorsqu'on a un numéro d'un groupe alors on ne peut plus avoir un autre numéro du même groupe. Ensuite il faut éliminer les numéros des autres groupes selon l'unité du numéro de référence. Si le premier numéro est disons 01 alors 11, 21, 31, etc seront interdits. La suite est à réfléchir par des tests.
Développeur web depuis + de 20 ans

Petit nouveau ! | 9 Messages

29 mars 2022, 16:31

Bonjour,
Si je comprends bien, tout le monde se casse les dents sur ce casse tête ?
De mon côté j'ai essayé d'écrire quelques routines, soit ça ne fonctionne pas, soit le résultat n'est pas bon, soit l'ordi plante.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

29 mars 2022, 17:50

Nous t'avons donné des pistes qui semblent prometteuses, mais ensuite c'est à toi de tester pour voir ce qui fonctionnerait et comment optimiser. :D
Quand tout le reste a échoué, lisez le mode d'emploi...

Petit nouveau ! | 9 Messages

31 mars 2022, 09:24

Bonjour,

M'ouias !
Des pistes ? Une à la rigueur, et encore.
google qui n'est pas mon amis m'en a proposé bien plus, mais à côté.
Tant pis.

De mon côté je fais des tests à tâtons, tant que le résultat correspond à ce que j'attends, je continu.
Je sais que c'est empirique et chronophage, mais je n'ai pas d'autres moyens.
Une fois que la procédure fonctionne, je simplifie avec des fonctions, et pour l'instant je sens qu'il y aura récursivité.

J'ai une erreur que je ne comprends pas dans ce code :
<html>
<head>
  <meta http-equiv="refresh" content="100000">
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<?php
for($min=0;$min<2;$min++)
{	$echo[$min] = '';
	//$min = 0; // 540 avec 1 et 180 avec 0
	$max = $min +6;
	$a=$b=$c=$d=0;
	$mem = array();
	for($a=$min;$a<$max;$a++)
	{	if(in_array($a,$mem)===false)
		{	$mem[0] = $a;
			for($b=$min;$b<$max;$b++)
			{	if(in_array($b,$mem)===false)
				{	$mem[1] = $b;
					for($c=$min;$c<$max;$c++)
					{	if(in_array($c,$mem)===false)
						{	$mem[2] = $c;
							for($d=$min;$d<$max;$d++)
							{	if(in_array($d,$mem)===false)
								{	$mem[3] = $d;
									$aa = $a - $min;
									$bb = $b - $min;
									$cc = $c - $min;
									$dd = $d - $min;
									@$echo[$min] .= '<br>'.$aa.$bb.'&nbsp'.$cc.$dd;
								$end[] = $a.$b.$c.$d;
									$mem[3] = '';
								}
							}
							$mem[2] = '';
							$echo[$min] .= '<br>';
						}
					}
					$mem[1] = '';
					$echo[$min] .=  '<hr>';
				}
			}
			$mem[0] = '';
			$echo[$min] .=  '<hr>';
		}
	}
	echo 'avec $min = '.$min.' et $max = '.$max.'  j\'ai '.sizeof($end).' combinaisons<br>';
}
echo 'les 20 premières lignes sont identiques,<br> c\'est après que ça dégénère, avec le 0<table border=1><tr><th>ce que j\'obtiens</th><th>ce que je voudrais</th></tr><tr align="center"><td valign="top">'.$echo[0].'</td><td>'.$echo[1].'</td></tr<></table>';
?>
J'essaye de faire toutes les combinaisons répondant à ma règle : xxxx avec x compris de 0 à 6 et aucune répétition de x.
Quand je boucle de 0 à 6 ça déconne, alors que de 1 à 7 ça fonctionne. Pourquoi ?

Mammouth du PHP | 1967 Messages

13 avr. 2022, 08:34

Si il n'est pas trop tard,
le chiffres des dizaines est toujours dans le même ordre
0X 1X 2X 3X ...
donc il reste juste à générer tous les classements possibles des 10 chiffres 0 à 9 et les placé à la place des X
Spols
pour les fan de rubik's cube ou pour les curieux ==> le portail francophone du rubik's cube

Petit nouveau ! | 9 Messages

13 avr. 2022, 09:58

Bonjour Spols et merci pour cette réponse.

Il n'est jamais trop tard, tant que le sujet n'est pas marqué résolu et que l'auteur est encore "récemment" venu sur le site.

C'est déjà mon approche avec mon précédent post.

Mammouth du PHP | 1967 Messages

13 avr. 2022, 14:53

voici le code que j'ai adapté de cette page https://codereview.stackexchange.com/qu ... from-array
<?php

function pc_permute($items, $perms = array( )) {
    $back = array();
    if (empty($items)) { 
		$back[] = "0$perms[0] 1$perms[1] 2$perms[2] 3$perms[3] 4$perms[4] 5$perms[5] 6$perms[6] 7$perms[7] 8$perms[8] 9$perms[9]";
    } else {
        for ($i = count($items) - 1; $i >= 0; --$i) {
             $newitems = $items;
             $newperms = $perms;
             list($foo) = array_splice($newitems, $i, 1);
             array_unshift($newperms, $foo);
             $back = array_merge($back, pc_permute($newitems, $newperms));
         }
    }
    return $back;
}
function pc_permute2($items) {
    foreach($items as $k1 => $items1) {
		foreach($items as $k2 => $items2) {
			if ($k1 == $k2) continue;
			foreach($items as $k3 => $items3) {
				if ($k1 == $k3 || $k2 == $k3) continue;
				foreach($items as $k4 => $items4) {
					if ($k1 == $k4 ||$k2 == $k4 || $k3 == $k4) continue;
					foreach($items as $k5 => $items5) {
						if ($k1 == $k5 || $k2 == $k5 || $k3 == $k5 || $k4 == $k5) continue;
						foreach($items as $k6 => $items6) {
							if ($k1 == $k6 || $k2 == $k6 || $k3 == $k6 || $k4 == $k6 || $k5 == $k6 ) continue;
							foreach($items as $k7 => $items7) {
								if ($k1 == $k7 || $k2 == $k7 || $k3 == $k7 || $k4 == $k7 || $k5 == $k7 || $k6 == $k7) continue;
								foreach($items as $k8 => $items8) {
									if ($k1 == $k8 ||$k2 == $k8 || $k3 == $k8 ||$k4 == $k8 || $k5 == $k8 ||$k6 == $k8 || $k7 == $k8) continue;
									foreach($items as $k9 => $items9) {
										if ($k1 == $k9 || $k2 == $k9 || $k3 == $k9 || $k4 == $k9 || $k5 == $k9 || $k6 == $k9 || $k7 == $k9 || $k8 == $k9) continue;
										foreach($items as $k10 => $items10) {
											if ($k1 == $k10 || $k2 == $k10 || $k3 == $k10 || $k4 == $k10 || $k5 == $k10 || $k6 == $k10 || $k7 == $k10 || $k8 == $k10 || $k9 == $k10) continue;
											$back[] = "0$items1 1$items2 2$items3 3$items4 4$items5 5$items6 6$items7 7$items8 8$items9 9$items10 ";
										}
									
									}
								
								}
							
							}
						
						}
					
					}
				
				}
			
			}
		
		}
	}
    return $back;
}
//var_dump(pc_permute([0,1,2,3,4,5,6,7,8,9]));
var_dump(pc_permute2([0,1,2,3,4,5,6,7,8,9]));
J'ai codé aussi la solution proposée (on liste tous et on exclu les mauvais) mais j'ai pas comparer les temps d'éxécution.
Par contre j'ai du monter la mémoire à 1G pour y arriver.

Si tu ne cherches qu'a obtenir une des lignes aléatoirement, ca simplifie le problème
Spols
pour les fan de rubik's cube ou pour les curieux ==> le portail francophone du rubik's cube