Swift : incompréhension des opérateurs && et || dans une boucle while
Derw
Membre
Bonjour.
Nouveau ici, comme en dev, j’ai commencé l’apprentissage de SWIFT avec Playgrounds. Or, j’ai un souci avec la boucle while
et les opérateurs &&
et ||
. Dans un exercice, je dois avancer tant que je n’ai pas activer 4 interrupteurs ET ramassé 3 gemmes. J’avais donc écrit ceci :
while compteurInterrupteurs < 4 && compteurGemmes < 3 {
Mais ce code ne fonctionne pas. Le personnage s’arrête dès qu’il a remplis une des 2 conditions.
Par contre, ce code fonctionne :
while compteurInterrupteurs < 4 || compteurGemmes < 3 {
C’est un bug ou je me trompe ?
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Le code fonctionne comme il doit fonctionner.
En fait la boucle doit s'arrêter si : compteurInterrupteurs >= 4 && compteurGemmes >=3
Elle continue quand ces conditions ne sont remplies, donc
while not(compteurInterrupteurs >= 4 && compteurGemmes >=3)
Après plutôt qu'écrire not( condition1 ET condition2), il peut être plus simple de la transformer comme ton second code.
Pour ce type de problème, il faut toujours construire une table de vérité binaire :
Là, tu peux voir s'il faut l'un ou l'autre.
La boucle while permet de répéter une séquence de code, TANT QUE une condition est valable.
``
Alors que ton algorithme défini une condition d'ARRET des tests !
La solution traditionnelle est d'utiliser l'opérateur booléen ! pour inverser la condition de sortie.
Moi j'aurais tapé quelque chose comme :
Le programme commence par vérifier la condition de sortie, conformément à ton cahier de charges.
compteurInterrupteurs == 4 && compteurGemmes == 3
puis l'opérateur ! inverse la condition de sortie pour obtenir l'information de répétition dont la boucle While a besoin.
J'ai mis des parenthèses après l'inversion, pour que Swift ne fasse pas d'erreur et inverse bien la totalité de la condition de sortie.
Sans les parenthèses, l'opérateur ! n'inverse que le résultat du test compteurInterrupteurs==4 et cela devient une belle source de bugs.
S'péce d'optimisateur fou ! Arrête d'embêter le novice avec des optimisations, donc des cas particuliers. Ne l'embrouille pas, pour qu'il puisse se concentrer sur la compréhension des mécanismes de base ..
Merci @Eric P.. Mais cela restait obscure...
En écrivant mon raisonnement pour vous répondre, j’ai compris pourquoi ! Donc maintenant c’est bon.
PS : c’est vrai qu’en prenant votre logique du not( condition1 ET condition2), j’avais moins de risque de me tromper...
Le code doit toujours être simple, et se rapprocher le plus possible de la formulation humaine du problème. C'est la principale raison pour laquelle Swift a été conçu.
Je me dois de réagir: ce genre de formulation est aussi source de problèmes si on n'a pas de garanties sur la manière dont la progression se fait. Avec par exemple, une séquence de 6 interrupteurs puis 4 gemmes, la boucle tournera de manière infinie. Le code d'Éric est donc plus sur.
Merci à tous pour vos contributions ! Et merci @Joanna Carter pour ton tableau !
C'est la stricte interprétation de la demande de l'exercice de programmation que Derw dt accomplir.
De plus, ce problème de dépassement des valeurs et de boucle infinie ne peut se produire que si l'application ne vérifie pas les données entrantes.
S'il faut 4 interrupteurs, l'application ne doit pas permettre d'en utiliser un 5iéme. Il faut un mécanisme de sécurité de ce genre là :
Drew, tu peux remarquer qu'il n'y pas de valeur numérique dans le code. Les paramètres sont définis dans des constantes au début du code. Les chiffres dans le code des fonctions c'est LE MAL ! Surtout si elles sont présentes à plusieurs endroits dans le code. Une erreur de saisie est vite arrivée, ce qui peut causer des bugs.
L'utilisation de constantes améliore la sécurité et la lisibilité du code. Sans parler de l'évolution éventuelle de l'application. Si le nombre de gemmes à trouver, passe à 4, il suffit de modifier une constante, au lieu de passer 10 minutes à chercher dans le code, toutes les lignes de code concernées (avec toujours le risque d'en oublier une, créant un nouveau bug).
Draken, je trouve ta solution très propre !
Tu as tout à fait raison, mais les deux approches ne sont pas exclusives Si on reste dans l'approche "simple" de l'exercice, utiliser des opérateurs
>=
plutôt que==
permet d'avoir un code plus sur car dépendant de moins d'hypothèses (et donc plus facilement réutilisable). Puis pour le cas particulier de "l'exercice", on peut toujours vérifier les données d'entrées.Je faisais aussi ma remarque dans le contexte d'un programme (par opposition à un exercice playground), où le code se trouve dans un environnement susceptible d'évoluer et certaines hypothèses invalidées. Si par exemple des super-gemmes sont ajoutées (qui comptent pour 5 normales, débloquées par achat in-app): un code basé sur des égalités devra être modifié, un code basé sur des minima ne devra pas l'être.