Track
/
Swift
Swift
/
Esercizi
/
Agente segreto Double-Null0111
Agente segreto Double-Null0111

Agente segreto Double-Null0111

Esercizio di apprendimento

Introduzione

Tipi di funzione

Se togliamo tutti i nomi e le etichette dalla firma di una funzione Swift, quello che resta è il tipo della funzione.

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) -> ()

Nota che i tipi delle prime due funzioni sono uguali, (String, Int) -> String, anche se le due firme sono diverse e le due funzioni funzionano in modo molto diverso. Entrambe prendono in input una String e un Int e restituiscono una String. E, come si vede dal tipo della terza funzione, anche se il corpo della funzione non sembra restituire nulla, in realtà restituisce implicitamente (), l'unico valore di tipo Void.

Questi tipi di funzione si possono usare allo stesso modo di qualsiasi altro tipo in Swift: per esempio, si possono usare nella dichiarazione di variabili o costanti. E dato che in Swift le funzioni sono valori, a queste costanti o variabili si possono assegnare funzioni già esistenti:

var stringAndIntToString: (String, Int) -> String

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

Come per le altre variabili e costanti, il valore che assegni deve essere del tipo corretto:

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

Tipi di funzione come tipi di parametro

Dato che i tipi di funzione si possono usare ovunque si possano usare altri tipi, ne consegue che possono essere usati come tipi di parametro, passati ad altre funzioni e chiamati dall'interno di quelle funzioni.

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"

Tipi di funzione come tipi restituiti

Allo stesso modo, i tipi di funzione possono essere usati come tipi restituiti dalle funzioni. In altre parole, si possono scrivere funzioni che creano e restituiscono altre funzioni. Quando si creano queste funzioni, la funzione restituita può usare gli altri parametri passati alla funzione o le variabili locali create all'interno della funzione genitore.

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

Istruzioni

Salve, agente Doppio-Zero0111.

La sua missione, se deciderà di accettarla, è scrivere un paio di strumenti per aiutarla a infiltrarsi nel quartier generale dell'UMBRA (Unione Minacce Bastarde Realmente Atroci) e recuperare i piani del loro ultimo, atroce piano. Per portare a termine questa missione le serviranno due strumenti.

1. Proteggere i piani segreti recuperati con una password

Una volta entrata in possesso dei piani segreti, dovrà proteggerli in modo che solo chi conosce la password possa recuperarli.

Per farlo, dovrà implementare la funzione protectSecret(_ secret: String, withPassword password: String) -> (String) -> String. Questa funzione restituirà un'altra funzione che accetta come input delle possibili stringhe di password. Se la password inserita è corretta, la nuova funzione restituisce il segreto nascosto; se invece la password non è corretta, la funzione restituisce "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. Generare una combinazione per aprire la loro cassaforte

Abbiamo scoperto che l'UMBRA basa tutte le combinazioni delle sue casseforti sul numero della stanza in cui si trovano. Le combinazioni delle casseforti si generano applicando ripetutamente una funzione speciale al numero della stanza. Quindi il primo numero della combinazione deriverà dall'applicazione della funzione al numero della stanza, il secondo dall'applicazione della funzione al primo numero, e il terzo dall'applicazione della funzione al secondo numero.

Tuttavia, l'UMBRA cambia regolarmente la funzione usata per generare le combinazioni, quindi il tuo strumento dovrà accettare sia un numero di stanza sia la funzione appropriata per generare la combinazione.

Implementa la funzione generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) per generare la combinazione che ti servirà.

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

generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Swift Exercism

Vuoi iniziare Agente segreto Double-Null0111?

Iscriviti a Exercism per imparare e padroneggiare Swift con 35 concetti116 esercizi e il mentoring di persone reali, tutto gratis.