Parcours
/
Swift
Swift
/
Exercices
/
Agent secret Double-Null0111
Agent secret Double-Null0111

Agent secret Double-Null0111

Exercice d'apprentissage

Introduction

Types de fonctions

Si l'on retire tous les noms et les étiquettes d'une signature de fonction Swift, il ne reste que le type de la fonction.

func shoppingList(item: String, quantity: Int) -> String {
  "You need to buy \(quantity) \(item)."
}
// shoppingList: (String, Int) -> String

func repeater(_ phrase: String, times: Int) -> String {
  var result = ""
  for _ in 1...times {
    result += phrase
  }
  return result
}
// repeater: (String, Int) -> String

func printString(line: String) {
  print(line)
}
// printString: (String) -> ()

Remarque que les types des deux premières fonctions sont identiques, (String, Int) -> String, même si les deux signatures sont différentes et que les deux fonctions se comportent de façon très différente. Toutes les deux prennent une String et un Int en entrée et renvoient une String. Et comme on peut le voir avec le type de la troisième fonction, même si le corps de la fonction ne semble rien renvoyer, il renvoie en fait implicitement (), la seule valeur de type Void.

Ces types de fonctions s'utilisent exactement comme n'importe quel autre type en Swift : on peut par exemple les utiliser dans la déclaration de variables ou de constantes. Et comme les fonctions sont des valeurs en Swift, on peut affecter des fonctions déjà existantes à ces constantes ou variables :

var stringAndIntToString: (String, Int) -> String

stringAndIntToString = shoppingList
stringAndIntToString("carrots", 3)
// => "You need to buy 3 carrots."

Comme pour les autres variables et constantes, la valeur que tu lui affectes doit être du bon type :

stringAndIntToString = printShoppingList
// Error: Cannot assign value of type '(String) -> ()' to type '(String, Int) -> String'

Types de fonctions comme types de paramètres

Comme les types de fonctions peuvent s'utiliser partout où d'autres types peuvent s'utiliser, il s'ensuit qu'ils peuvent servir de types de paramètres, être passés à d'autres fonctions et être appelés depuis ces fonctions.

func apply3(to str: String, function f: (String, Int) -> String) -> String {
  f(str,3)
}
// apply3: ([String], (String, Int) -> String) -> [String]

apply3(to: "eggs", function: shoppingList)
// => "You need to buy 3 eggs."

apply3(to: "eggs", function: repeater)
// => "eggseggseggs"

Types de fonctions comme types de retour

De la même manière, les types de fonctions peuvent servir de types de retour pour des fonctions. Autrement dit, on peut écrire des fonctions qui créent et renvoient d'autres fonctions. Lorsqu'on crée ces fonctions, la fonction renvoyée peut utiliser les autres paramètres passés à la fonction ou les variables locales créées à l'intérieur de la fonction parente.

func makeAdder(base: Int) -> (Int) -> Int {
  func adder(_ i: Int) -> Int {
    base + i
  }
  return adder
}
// makeAdder: (Int) -> (Int) -> Int

let add10 = makeAdder(base: 10)
// add10: (Int) -> Int

let subtract20 = makeAdder(base: -20)
// subtract10: (Int) -> Int

add10(5)
// => 15

subtract20(5)
// => -15

Instructions

Bonjour, Agent Double-Null0111.

Ta mission, si tu choisis de l'accepter, est d'écrire deux outils pour t'aider à infiltrer le quartier général d'UMBRA (United Minions Being Really Awful) et à récupérer les plans de leur dernière machination vraiment atroce. Deux outils te seront nécessaires pour mener à bien cette mission.

1. Protège les plans secrets récupérés à l'aide d'un mot de passe

Une fois les plans secrets en ta possession, tu devras les protéger pour que seules les personnes qui connaissent le mot de passe puissent les récupérer.

Pour ce faire, tu devras implémenter la fonction protectSecret(_ secret: String, withPassword password: String) -> (String) -> String. Cette fonction renvoie une autre fonction qui prend en entrée des strings pouvant être le mot de passe. Si le mot de passe saisi est correct, la nouvelle fonction renvoie le secret dissimulé, mais si le mot de passe est incorrect, la fonction renvoie « Sorry. No hidden secrets here. »

let secretFunction = protectSecret("Steal the world's supply of french fries!", withPassword: "5up3r53cr37")

secretFunction("Open sesame")
// Returns "Sorry. No hidden secrets here."

secretFunction("5up3r53cr37")
// Returns "Steal the world's supply of french fries!"

2. Génère une combinaison pour ouvrir leur coffre-fort

Nous avons appris qu'UMBRA base toutes ses combinaisons de coffre-fort sur le numéro de la salle où se trouve le coffre. Ces combinaisons sont générées en appliquant de façon répétée une fonction spéciale au numéro de la salle. Ainsi, le premier nombre de la combinaison provient de l'application de la fonction au numéro de la salle, le deuxième de l'application de la fonction au premier nombre, et le troisième de l'application de la fonction au deuxième nombre.

Cependant, UMBRA change régulièrement la fonction utilisée pour générer les combinaisons, donc ton outil devra prendre à la fois un numéro de salle et la fonction appropriée pour générer la combinaison.

Implémente la fonction generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) pour générer la combinaison dont tu auras besoin.

func makeCombo(_ x: Int) -> Int {
  (x * 13) % 256
}

generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Swift Exercism

Prêt à commencer Agent secret Double-Null0111 ?

Inscris-toi sur Exercism pour apprendre et maîtriser Swift avec 35 concepts116 exercices, et un vrai mentorat humain, le tout gratuitement.