Problème boucle en java

Fermé
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 - 25 mars 2013 à 18:43
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 - 28 mars 2013 à 16:21
Bonjour, je débute en java et je commence à travailler avec les tableaux et j'essaie d'écrire un programme qui va trier 5 mots en ordre croissant.

J'ai un problème avec ma boucle while

while(listeMots[0].compareTo(listeMots[1]) > 0 && listeMots[1].compareTo(listeMots[2]) > 0  && listeMots[2].compareTo(listeMots[3]) > 0  && listeMots[3].compareTo(listeMots[4]) > 0)


dès qu'une seule de ses conditions est réuni, la boucle s'arrêtte alors que je veux qu'elle s'arrêtte seulement quand toute les conditions sont réunis, donc quand tous les mots sont bien en ordre croissant dans le tableau.

Pourtant avec des Et c'est ce que s'est censé faire, je ne comprend pas







A voir également:

7 réponses

KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
25 mars 2013 à 19:31
Il faut inverser ta condition, pour qu'elle continue si elle est vraie et s'arrête quand elle est fausse.

while( ! (listeMots[0].compareTo(listeMots[1]) > 0
       && listeMots[1].compareTo(listeMots[2]) > 0 
       && listeMots[2].compareTo(listeMots[3]) > 0
       && listeMots[3].compareTo(listeMots[4]) > 0))

En logique booléenne, cette négation de conjonction est équivalente à une disjonction de négation, ce qui rend la condition d'arrêt un peu plus explicite :

while(listeMots[0].compareTo(listeMots[1]) <= 0
   || listeMots[1].compareTo(listeMots[2]) <= 0 
   || listeMots[2].compareTo(listeMots[3]) <= 0
   || listeMots[3].compareTo(listeMots[4]) <= 0)

Remarque 1 : attention à bien prendre en compte les cas d'égalité, parce qu'il faut que ta boucle s'arrête dans tous les cas (si tu as deux mots identiques, tu n'auras jamais l'un qui sera strictement supérieur à l'autre).

Remarque 2 : il me semble que cette condition va te renvoyer un ordre décroissant, pour un ordre croissant il faut faire l'inverse.

while(listeMots[0].compareTo(listeMots[1]) > 0
   || listeMots[1].compareTo(listeMots[2]) > 0 
   || listeMots[2].compareTo(listeMots[3]) > 0
   || listeMots[3].compareTo(listeMots[4]) > 0)
1
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
25 mars 2013 à 18:55
Hum, à mon avis tu as juste un problèmes avec les parenthèses, il faut en mettre pour définir chaque terme proprement:

while((listeMots[0].compareTo(listeMots[1]) > 0) && (listeMots[1].compareTo(listeMots[2]) > 0)  && (listeMots[2].compareTo(listeMots[3]) > 0)  && (listeMots[3].compareTo(listeMots[4]) > 0))

0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
25 mars 2013 à 19:33
Les parenthèses ne posent pas de problème ici, il n'y a que des && donc il n'y a pas d'ambiguïté.
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
25 mars 2013 à 19:35
Hé oui j'ai fait cette remarque en partant du pascal, qui aurait exigé les parenthèses pour fonctionner!
0
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 2
Modifié par Balthazar2 le 25/03/2013 à 22:45
Salut, je ne veux pas contredire, car je ne suis surement pas aussi connaissant que vous, mais si je met <= 0 au lieu de >=0 la condition sera fausse dès le début et je n'entrerai jamais dans la boucle non ?

Sinon, je n'ai peut-être pas la meilleure technique, mais

j'ai une variable plusPetitMot que j'initialise à un truc du genre "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"

avant mon while, plusPetitNombre prend la valeur du mot en première position.

ce que je fais c'est que j'ai une boucle for a l'intérieur du while qui va se charger de trouver le plus petit nombre qui sera placer ensuite en première position, ce qui me pose problème, car je viens de me rendre compte que j'écrase la première position du tableau par la valeur de plusPetitMot au lieu de permuter plusPetitMot avec la position du premier mot que j'ai entrer. J'ai chercher et la bonne technique consiste a passer par une variable temporaire, mais le soucis c'est que je ne sais pas d'avance le mot qui sera permuter.

ensuite plusPetitNombre prend la valeur du deuxieme élément du tableau et je dois revenir dans le for pour trouver le deuxieme plus petit et ainsi de suite.

ça me donne quelque chose comme ça.
plusPetitNombre a la valeur du premier élément du tableau au début de la boucle.

int i=0; 
int j=0; 
int k=4; 
while(listeMots[0].compareTo(listeMots[1]) >= 0 &&  
      listeMots[1].compareTo (listeMots[2]) >= 0  &&  
      listeMots[2].compareTo(listeMots[3]) >= 0  &&  
      listeMots[3].compareTo(listeMots[4]) >= 0) 
{ 
               for(j=0;j<k;j++) 
               { 
                         if(plusPetitMot.compareTo(listeMots[j+1] >0) 
                                plusPetitMot = listeMots[j+1];  
               } 
               //permuter plusPetitMot avec listeMots[i] 
               plusPetitMot = listeMots[i+1]; 
               i++; 
               k--; 
} 


Le truc c'est que dès qu'une des 4 condition est fausse, la boucle while prend fin, ce que je ne comprend pas

Par exemple si j'entre les mots dans cet ordre :
tomate
patate
concombre
carotte
asperge

chaque mot est > que le précédent donc toute els conditions sont vrai.

Comme j'écrase tomate par plusPetitMot, le tableau se compose ensuite comme ceci après un premier tour de boucle

asperge
patate
concombre
carotte
asperge

la première condition est fausse, fin de la boucle, alors que je veux qu'elle s'arrête seulement quand chaque élément du vecteur < que le précédent

si j'entre les mot dans cet ordre :

tomate
asperge
concombre
carotte
patate

je n'entre même pas dans ma boucle while, première condition vrai, mais la seconde fausse, fin de la boucle.

Il y a donc clairement un problème dans les conditions que j'ai mis dans le while que je n'arrive pas à identifier.
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
26 mars 2013 à 07:09
"si je met <= 0 au lieu de >=0 la condition sera fausse dès le début et je n'entrerai jamais dans la boucle"
Il est surtout important de noter que j'ai changé les && en ||
C'est à dire qu'il faudrait que TOUTES les conditions soient fausses pour sortir de la boucle, mais on continue tant qu'il y en a au moins une de vraie (c'est à dire tant qu'il y a au moins un élément non trié)
Après <= ou >= ça va te changer l'ordre (soit tout croissant, soit tout décroissant), mais ce sera trié.

"j'ai une variable plusPetitMot que j'initialise à un truc du genre "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
Oublie ce genre de bidouille, ça fonctionne peut-être sur ton cas particulier, mais ce n'est pas généralisable.

"Le truc c'est que dès qu'une des 4 condition est fausse, la boucle while prend fin, ce que je ne comprend pas "
C'est parce que tu as des &&. Si tu as VRAI ET FAUX, ton résultat sera FAUX, donc dès qu'une condition qui est évalué à FAUX, toute ta conjonction est évaluée à FAUX, et ta boucle s'arrête.
D'où l'intérêt de mettre des || ou d'inverser le test avec ! (voir tout ce que j'ai dit avant)

Remarque : dans ce genre d'algorithme, on ne fait normalement jamais un test à rallonge comme ça.
On évaluerai plutôt un booléen ("continuer" par exemple), qu'on initialise à true et qu'on utilise dans un "while(continuer)" ensuite on changerai sa valeur dans la boucle for pour avoir false quand on n'a pas fait de permutation, ce qui arrête le tri.
On retrouve l'idée de "généralisation" dont je parlais un peu plus haut, à savoir que cette méthode sera valable pour un tri de 5 mots, comme celui d'un milliards de valeurs (ou plus...)
0
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 2
26 mars 2013 à 15:28
Effectivement il fallait des ou, j'ai lu un peu vite :s



Je pourrais aussi initialiser mon plusPetitMot à "" et lui donner la valeur de listeMots[0]; juste avat mes boucle de tri.

J'avoue avoir du mal à savoir quelle façon de faire est la plus opti, mais j'ai un peu changer ma façon de faire, car je n'arrivais pas à savoir d'avance quelle était l'indice du plus petit mot dans le tableau listeMots.

Je me suis fais un deuxième tableau qui lui contiendra les valeurs en ordre croissant, la boucle continue tant qu'il n'est pas rempli.

Mais difficile d'optimiser le tri, car inutile de comparer les autre mot avec un mot qui a été placé dans le tableau croissant[] et il ne faut non plus. Par exemple dans mon exemple asperge est le plus petit, au second tour de boucle for, il ne doit plus faire parti du tri. Et je ne dois pas non plus comparer un mot avec lui même.

Mais qu'entend tu par test à rallonge ?
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
26 mars 2013 à 19:31
Je pourrais aussi initialiser mon plusPetitMot à ""
Oublie ce genre de bidouilles, ça marchera peut-être pour des String mais rarement en général.

"lui donner la valeur de listeMots[0];"
Ça c'est déjà une meilleur idée.

"je n'arrivais pas à savoir d'avance quelle était l'indice du plus petit mot dans le tableau listeMots."
Tu ne le sais jamais d'avance, c'est à ça que doit servir la boucle for : à chercher un couple d'éléments à permuter.

"Je me suis fais un deuxième tableau"
A priori c'est une mauvaise idée.

"difficile d'optimiser le tri"
Avant d'optimiser le tri, il faudrait d'abord commencer à faire quelque chose d'à peu près correct...

"qu'entend tu par test à rallonge ?"

Ceci est un "test à rallonge" :
listeMots[0].compareTo(listeMots[1]) > 0
   || listeMots[1].compareTo(listeMots[2]) > 0 
   || listeMots[2].compareTo(listeMots[3]) > 0
   || listeMots[3].compareTo(listeMots[4]) > 0

Si tu n'as plus 5 valeurs, mais 4 ou 6 il faut changer ton code, imagines que tu as 100 valeurs à trier (ce qui est assez peu), il est évident que tu ne devras pas coder 100 clauses disjonctives dans ta condition d'arrêt ! Il faut réfléchir au plus simple dans ta condition du while, je t'ai donné une manière de faire ce matin avec mon booléen "continuer", il y en a bien sûr d'autres.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 2
Modifié par Balthazar2 le 26/03/2013 à 20:18
La technique que je connais pour permuter 2 éléments c'est quelque chose comme ça

temp = tab[0];
tab[0] = tab[1];
tab[1] = temp;

Mais dans ma boucle for

for(j=0;j<k;j++)  
               {  
                         if(plusPetitMot.compareTo(listeMots[j+1] >0)  
                                plusPetitMot = listeMots[j+1];   
               }  




Je sais que la boucle for doit chercher les éléments à permuter, mais comment faire pour que la boucle trouve la position du mot le plus petit dans le tableau listeMot[], c'est là que je bloque.

temp = listeMots[i];
listeMots[i] = plusPetitMots;
??? = temp;
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
Modifié par KX le 26/03/2013 à 20:26
C'est parce que ton "plusPetitMot" ne sert pas à grand chose... il serait plus intéressant d'avoir un indice sur ce plus petit mot afin de le permuter. Ça donnerait quelque chose comme ça :

if (listeMots[indiceMin].compareTo(listeMots[j] > 0)
{
    temp = listeMots[indiceMin];
    listeMots[indiceMin] = listeMots[j];
    listeMots[j] = temp;
}
0
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 2
Modifié par Balthazar2 le 26/03/2013 à 20:42
Disons que je trouvais intéressant de permuter seulement quand le plus petit mot de la liste a été trouver.

J'essayais de trouver le plus petit mot et de le permuter avec le mot en première position. le deuxième avec celui en deuxième position et ainsi de suite.
0
KX Messages postés 16754 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 020
26 mars 2013 à 20:50
Rien ne t'en empêche (c'est même mieux), mais il faut le faire bien.

// recherche du plus petit mot entre A et B 

indiceMin=A;
for (int i=A; i<B; i++)  
    if (listeMots[indiceMin].compareTo(listeMots[i] > 0)  
        indiceMin = i;
 
// permutation du pus petit mot avec le mot en position P

temp = listeMots[indiceMin];
listeMots[indiceMin] = listeMots[P];
listeMots[P] = temp;
0
Balthazar2 Messages postés 138 Date d'inscription mardi 16 octobre 2012 Statut Membre Dernière intervention 29 janvier 2016 2
28 mars 2013 à 16:21
Salut, désolé du retard.

Mais merci de tes conseils ça m'a beaucoup aider. Tu dois penser que je suis un noob surtout avec ma toute première question XD
0