Trilhas
/
Swift
Swift
/
Exercícios
/
Agente Secreto Double-Null0111
Agente Secreto Double-Null0111

Agente Secreto Double-Null0111

Exercício de aprendizagem

Introdução

Tipos de função

Se removermos todos os nomes e rótulos de uma assinatura de função em Swift, o que sobra é o tipo da função.

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

Repare que os tipos das duas primeiras funções são iguais, (String, Int) -> String, mesmo que as duas assinaturas sejam diferentes e as duas funções funcionem de maneiras bem distintas. As duas recebem uma String e um Int como entrada e retornam uma String. E, como dá para ver pelo tipo da terceira função, mesmo que o corpo da função não pareça retornar nada, na verdade ele retorna () implicitamente, o único valor do tipo Void.

Esses tipos de função podem ser usados da mesma forma que qualquer outro tipo em Swift. Por exemplo, podem ser usados na declaração de variáveis ou constantes. E, como funções são valores em Swift, funções que já existem podem ser atribuídas a essas constantes/variáveis:

var stringAndIntToString: (String, Int) -> String

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

Como acontece com outras variáveis/constantes, o valor que você atribui precisa ser do tipo correto:

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

Tipos de função como tipos de parâmetro

Como os tipos de função podem ser usados em qualquer lugar onde outros tipos podem ser usados, eles também podem ser usados como tipos de parâmetro, passados para outras funções e chamados de dentro delas.

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"

Tipos de função como tipos de retorno

Da mesma forma, os tipos de função podem ser usados como tipos de retorno de funções. Em outras palavras, você pode escrever funções que criam e retornam outras funções. Ao criar essas funções, a função retornada pode usar os outros parâmetros passados para a função ou as variáveis locais criadas dentro da função pai.

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

Instruções

Olá, Agente Double-Null0111.

Sua missão, caso você decida aceitá-la, é escrever um par de ferramentas para ajudar você a se infiltrar no quartel-general da UMBRA (United Minions Being Really Awful) e recuperar os planos do esquema mais recente e realmente horrível deles. Você vai precisar de duas ferramentas para cumprir esta missão.

1. Proteja os planos secretos recuperados com uma senha

Depois de conseguir os planos secretos, você vai precisar protegê-los para que só quem sabe a senha possa recuperá-los.

Para isso, você vai precisar implementar a função protectSecret(_ secret: String, withPassword password: String) -> (String) -> String. Essa função retorna outra função que recebe possíveis strings de senha como entrada. Se a senha digitada estiver correta, a nova função retorna o segredo escondido; mas se a senha estiver incorreta, a função retorna "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. Gere uma combinação para abrir o cofre deles

Descobrimos que a UMBRA baseia todas as combinações dos seus cofres no número da sala em que está localizada. As combinações dos cofres são geradas aplicando repetidamente uma função especial ao número da sala. Assim, o primeiro número da combinação vem da aplicação da função ao número da sala, o segundo vem da aplicação da função ao primeiro número, e o terceiro, da aplicação da função ao segundo número.

No entanto, a UMBRA muda com frequência a função usada para gerar as combinações, então sua ferramenta vai precisar receber tanto um número de sala quanto a função adequada para gerar a combinação.

Implemente a função generateCombination(forRoom room: Int, usingFunction f: (Int) -> Int) -> (Int, Int, Int) para gerar a combinação que você vai precisar.

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

generateCombination(forRoom: 227, usingFunction: makeCombo)
// Returns (135, 219, 31)
Editar via GitHub O link abre em uma nova janela ou aba
Swift Exercism

Tudo pronto para começar Agente Secreto Double-Null0111?

Crie sua conta no Exercism para aprender e dominar Swift com 35 conceitos116 exercícios e mentoria humana de verdade, tudo de graça.