Exercice : fonction année bissextile ou non ?

Soit un exercice avec l’intitulé suivant et réalisable avec des if… else… else if… :

Déterminer si une année est bissextile ou non demande de prendre plusieurs décisions :

L’année est-elle divisible par 4 ?

Si oui, l’année est-elle divisible par 100 ?

Si non, c’est une année bissextile.
Si oui, l’année est-elle divisible par 400 ?

Si non, ce n’est pas une année bissextile.
Si oui, c’est une année bissextile.

Ce processus de prise de décision peut être masqué au sein d’une fonction.

La fonction number(_:, isDivisibleBy:) a été intégrée à cette aire de jeux pour rendre l’exercice un peu plus simple. Voici une fonction incomplète permettant de déterminer si une année est bissextile ou non :

func isLeapYear(_ year: Int) -> Bool {
if number(year, isDivisibleBy: 4) {
    return true
} else {
    return false
}

}

// Doit être vrai
isLeapYear(2000)
// Doit être faux
isLeapYear(1900)
// Doit être vrai
isLeapYear(2012)
// Doit être faux
isLeapYear(2017)

J’ai mis le code suivant mais je ne vois pas comment tester si ce n’est pas divisible par 100… Bref, je ne vois pas comment enchainer des conditions à réaliser uniquement si la précédente est vrai ou fausse.

Sans donner la réponse, quelqu’un pourrait-il donner une piste ?

merci

func isLeapYear(_ year: Int) -> Bool {
if number(year, isDivisibleBy: 4) && number(year, isDivisibleBy: 100) && number(year, isDivisibleBy: 400) {
    return true
} else {
    return false
}

}

func testConditions() -> Bool {
    let condition1 = true
    let condition2 = true
    let condition3 = true
    if condition1 == true {
        if condition2 == true {
            if condition3 == true {
                // Code exécuté seulement si les 3 tests sont positifs
                return true
            }
        }
    }
    // Code exécuté si l'un des 3 tests échoue
    return false
}

Pas besoin de tester l’égalité avec true si la valeur est déjà de type Bool, ce qui permet une écriture plus compacte :

func testConditionsCompact() -> Bool {
        let condition1 = true
        let condition2 = true
        let condition3 = false
        if condition1 {
            if condition2 {
                if condition3 {
                    // Code exécuté seulement si les 3 tests sont positifs
                    return true
                }
            }
        }
        // Code exécuté si l'un des 3 tests échoue
        return false
    }

Merci pour la piste :slight_smile:

Pour info dans “Les bases de la programmation” tu as un exercice similaire qui est corrigé si tu veux :slight_smile:

Je patauge.
Je teste les années avec des if mais, sur 4 dates données, le premier if ne teste que 3 dates, le second 2, le 3è une et la dernière aucune.

func isLeapYear(_ year: Int) -> Bool {
var anneeDivisiblePar4 = true
var anneeDivisiblePar100 = true
var anneeDivisiblePar400 = true

if number(year, isDivisibleBy: 4) {
    anneeDivisiblePar4 = true
    }
if number(year, isDivisibleBy: 100) {
    anneeDivisiblePar100 = true
}
if number(year, isDivisibleBy: 400) {
    anneeDivisiblePar400 = true
}

if anneeDivisiblePar4 == true {
    if anneeDivisiblePar100 == false {
        if anneeDivisiblePar400 == true {
return true
        }
    }
}
    return false
}

Mais tout est en C# dans ton livre…

func isLeapYear(_ year: Int) -> Bool {
var anneeDivisiblePar4 = true
var anneeDivisiblePar100 = true
var anneeDivisiblePar400 = true

if number(year, isDivisibleBy: 4) {
    anneeDivisiblePar4 = true
    }
if number(year, isDivisibleBy: 100) {
    anneeDivisiblePar100 = true
}
if number(year, isDivisibleBy: 400) {
    anneeDivisiblePar400 = true
}

if anneeDivisiblePar4 == true {
    if anneeDivisiblePar100 == false {
        if anneeDivisiblePar400 == true {
return true
        }
    }
}
    return false
}

Mon DIEU ! Toutes ces variables intermédiaires ne servant à rien !! :flushed:

Voici quelque chose de plus simple : (non testé, tapé de tête).

func isLeapYear(_ year: Int) -> Bool {
        if number(year, isDivisibleBy: 4) {
            if number(year, isDivisibleBy: 100) == false {
                if number(year, isDivisibleBy: 400) {
                    return true
                }
            }
        }
        return false
    }

Ou d’une autre manière, en évitant la comparaison du test de division 100 avec false, grâce à l’opérateur ! qui inverse une valeur boléenne. C’est plus « pro », mais moins visible dans le code par un novice.

func isLeapYear(_ year: Int) -> Bool {
        if number(year, isDivisibleBy: 4) {
            if !number(year, isDivisibleBy: 100) {
                if number(year, isDivisibleBy: 400) {
                    return true
                }
            }
        }
        return false
    }

Même si mon code est lourd , ne devrait il pas pour autant fonctionner ? Pourquoi tous les ‹ if › ne sont-ils pas testés ?

Je viens de tester ton code, il me retourne des false pour les 4 dates alors que :
// Doit être vrai
isLeapYear(2000)
// Doit être faux
isLeapYear(1900)
// Doit être vrai
isLeapYear(2012)
// Doit être faux
isLeapYear(2017)

Je ne sais pas. Peut-tu me donner le code de la fonction number(year, isDivisibleBy) pour que je puisse regarder l’intégralité du processus ?

Malheureusement non : elle est intégrée au didacticiel (leçon 11 : ibook Introduction au développement d’apps en Swift)

C’est pas grave, en relisant l’énoncé, je pense que l’erreur viens de ta lecture de l’algorithme.

Déterminer si une année est bissextile ou non demande de prendre plusieurs décisions :

L’année est-elle divisible par 4 ?

Si oui, l’année est-elle divisible par 100 ?

Si non, c’est une année bissextile.
Si oui, l’année est-elle divisible par 400 ?

Si non, ce n’est pas une année bissextile.
Si oui, c’est une année bissextile.

J’ai vérifié sur Wikipédia :

Depuis l'ajustement du calendrier grégorien, l'année sera bissextile (elle aura 366 jours)

1 : si l'année est divisible par 4 et non divisible par 100, ou
2 : si l'année est divisible par 400.
Sinon, l'année n'est pas bissextile (elle a 365 jours).

Tu vérifie si l’année est divisible par 4 ET non divisible par 100 ET divisible par 400.

Alors que le bon test c’est :

(année divisible par 4 ET non divisible par 100) OU année divisible par 400

Oui, c’était bien une erreur d’algorithme. J’ai un programme opérationnel avec l’algo corrigé.

2000  :  true
1900  :  false
2012  :  true
2017  :  false


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        for annee in [2000, 1900, 2012, 2017] {
            print (annee, " : ", testerAnnee(annee))
        }
    }
    
    func isDivisible(_ valeur:Int, by:Int) -> Bool {
        return valeur % by == 0
   }
    
    func testerAnnee(_ year:Int) -> Bool {
      // Code effacé pour te laisser trouver par toi-même
      // Je te le donne si tu en exprime le désir
    }
    
}

Si je devais deviner le contenu de la fonction estDivisiblePar j’imagine qu’il doit y avoir uniquement :
return nombre % diviseur == 0

Et c’est exactement ce que j’ai tapé dans la fonction isDivisible(), écrite pour avoir une syntaxe similaire à la fonction number() utilisée par Fanfan.

En fait, j’ai fait un copier-coller de l’énoncé tel qu’il est dans le livre…
Bon, je me mets au boulot :+1:t2:

Ah oui, j’ai lu trop vite, je m’étais arrêté à ta question où tu demandais le contenu de la fonction ^^

Alors voici mon code qui me renvoie les réponses true, false, true, false pour 2000, 1900, 2012 et 2017 :

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    
    for annee in [2000, 1900, 2012, 2017] {
        print (annee, " : ", testerAnnee(annee))
    }
}

func isDivisible(_ valeur:Int, by:Int) -> Bool {
    return valeur % by == 0
}

func testerAnnee(_ annee:Int) -> Bool {
    if (isDivisible(annee, by: 4) && !isDivisible(annee, by: 100)) || (isDivisible(annee, by: 400)) {
    return true
    }
    return false
}

}

Comme l’énoncé parlait de if else et non d’opérateurs logiques, j’ai codé la fonction comme ça :

func testerAnnee(_ year:Int) -> Bool {
               
        if isDivisible(year, by: 4) {
            if !isDivisible(year, by: 100) {
                return true
            }
        }
        
        if isDivisible(year, by: 400) {
            return true
        }
        
        return false
    }
1 « J'aime »