Trilhas
/
Swift
Swift
/
Exercícios
/
A 1ª Regra do Clube de Poesia
A 1ª Regra do Clube de Poesia

A 1ª Regra do Clube de Poesia

Exercício de aprendizagem

Introdução

Importação

A biblioteca padrão do Swift oferece muitos recursos, mas você pode acessar funcionalidades adicionais importando bibliotecas e frameworks externos. Esses módulos podem vir diretamente do projeto Swift (como o Swift Argument Parser), de frameworks da plataforma Apple (como o Foundation e o Network Framework) ou de bibliotecas de código aberto de terceiros (como o SwiftyBeaver).

Módulos principais como o Foundation, uma das bibliotecas mais usadas do Swift, já vêm com o conjunto de ferramentas do Swift. Bibliotecas de terceiros precisam ser adicionadas à configuração do seu projeto (por exemplo, usando o Swift Package Manager) antes de poderem ser importadas.

A importação de módulos é feita escrevendo a palavra-chave import seguida do nome do módulo. Assim, dá para importar o Foundation adicionando o seguinte ao seu programa.

import Foundation

Importar um módulo deixa os tipos, métodos e funções dele disponíveis para o seu código. Por exemplo, importar o Foundation estende o String com métodos utilitários úteis, como components(separatedBy:).

Por convenção, as instruções import ficam no topo do arquivo Swift, para que as dependências sejam visíveis de imediato para quem lê o código.

Indexação de strings

Você pode acessar caracteres individuais de uma String usando o método de subscrito que se usa com arrays. No entanto, os índices usados para strings não são inteiros e não podem ser usados diretamente. Em vez disso, eles precisam ser calculados a partir de algum outro índice conhecido, como startIndex, que aponta para a posição do primeiro caractere em uma string não vazia, usando os métodos disponíveis nas bibliotecas String e NSString (quando o módulo Foundation é importado, as strings em Swift têm acesso a todas as propriedades e métodos do NSString).

Por exemplo, dada a seguinte string:

let csv = "apple,pear,peach,orange,cherry,lime,goosberry"

Não dá para escrever csv[21] para obter o "g" de "orange"; em vez disso, é preciso calcular um valor do tipo String.Index e passar esse índice. Repare que esses índices não foram feitos para serem consumidos por humanos diretamente. Eles são o que se chama de índices opacos, já que os humanos não precisam saber o que há dentro deles.

let index = csv.index(csv.startIndex, offsetBy: 21)
csv[index]
// "g"
print(index)
// prints Index(_rawBits: 1376513)

Repare, porém, que se o deslocamento não for um índice válido, ou seja, se ele retornar o índice antes de startIndex ou depois de endIndex, a operação vai gerar um erro e derrubar o programa. Para evitar esse problema, dá para especificar um índice limite. Isso retorna um índice opcional e devolverá nil para índices que de outra forma seriam inválidos.

let tooFar = csv.index(csv.startIndex, offsetBy: 200)
// error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
let tooFarButSafe = csv.index(csv.startIndex, offsetBy: 200, limitedBy: csv.endIndex)
// nil

Além disso, índices não podem ser compartilhados entre strings. Por exemplo, usar o index do "g" em "orange" calculado acima para indexar a string fam = "This is my family: 👨‍👩‍👦‍👦, this is our dog: 🐶, this is our cat: 🐱!", ou seja, fam[index], vai derrubar o programa.

Há muitos motivos para tudo isso, mas basicamente todos se resumem a "Unicode é complicado".

De modo geral, se você precisa de acesso aleatório a caracteres individuais, provavelmente é melhor usar outra estrutura de dados, como Array<Character>.

Alguns métodos úteis

O Swift tem os métodos first e last para obter o primeiro e o último caractere de uma string. Esses métodos retornam um caractere opcional, então, se a string estiver vazia, eles retornam nil.

let str = "Hello, world!"
print(str.first) // Prints Optional("H")
print(str.last)  // Prints Optional("!")

Você também pode usar os métodos prefix e suffix para obter uma substring de uma string. Esses métodos recebem um inteiro como argumento e retornam uma substring com os primeiros ou os últimos n caracteres da string.

let str = "Hello, world!"
print(str.prefix(5)) // Prints "Hello"
print(str.suffix(6)) // Prints "world!"

Métodos de string

Trabalhar com texto é uma tarefa comum em programação. O Swift, junto com o framework Foundation, oferece muitos métodos e propriedades convenientes para inspecionar, transformar e manipular strings.

Dividindo strings com components(separatedBy:)

Para dividir uma string em um array de substrings com base em um delimitador, use components(separatedBy:) (é preciso importar o Foundation):

import Foundation

let sentence = "Hello, world!"
let words = sentence.components(separatedBy: " ")
print(words) // Prints ["Hello,", "world!"]

Verificando prefixos e sufixos com hasPrefix(_:) e hasSuffix(_:)

Para verificar se uma string começa ou termina com uma sequência específica de caracteres, use hasPrefix(_:) e hasSuffix(_:):

let greeting = "Hello, world!"
print(greeting.hasPrefix("Hello"))  // Prints true
print(greeting.hasSuffix("world!")) // Prints true

Alterando maiúsculas e minúsculas

Você pode alterar as maiúsculas e minúsculas de uma string usando estes métodos e propriedades padrão:

  • lowercased(): retorna uma cópia da string em minúsculas.
  • uppercased(): retorna uma cópia da string em maiúsculas.
  • capitalized: retorna uma cópia em que a primeira letra de cada palavra fica maiúscula (do Foundation).
let greeting = "hello, world!"
print(greeting.lowercased())  // Prints "hello, world!"
print(greeting.uppercased())  // Prints "HELLO, WORLD!"
print(greeting.capitalized)   // Prints "Hello, World!"

Substituindo substrings com replacingOccurrences(of:with:)

Para substituir todas as ocorrências de uma substring alvo por outra string, use replacingOccurrences(of:with:) (do Foundation):

let greeting = "Hello, world!"
let updated = greeting.replacingOccurrences(of: "world", with: "Swift")
print(updated) // Prints "Hello, Swift!"

Juntando strings com joined(separator:)

O método joined(separator:) pertence a coleções de strings, como [String]. Ele junta os elementos em uma única string usando um separador:

let words = ["Hello", "world"]
let sentence = words.joined(separator: ", ")
print(sentence) // Prints "Hello, world"

Instruções

Um novo clube de poesia abriu na cidade, e você está pensando em ir. Como já houve incidentes no passado, o clube tem uma política de entrada bem específica que você vai precisar dominar antes de tentar entrar.

Há duas portas no clube de poesia, e as duas têm guardas. Para conseguir entrar, você vai precisar descobrir a senha do dia:

1. Divida uma string em linhas individuais

A primeira coisa que você precisa fazer é dividir o poema em linhas individuais. O guarda vai recitar um poema, e você vai ter que dividi-lo em linhas.

Implemente a função splitOnNewlines, que recebe uma string e a divide em um array de strings, usando o caractere de nova linha como delimitador. A função deve retornar um array de strings, em que cada string é uma linha do poema.

splitOnNewlines("Hello.\nHow are you?\n\nI'm doing fine.")
// returns ["Hello." ,"How are you?", "", "I'm doing fine"].

2. Porta da frente

  1. O guarda vai recitar um poema
  2. Você vai ter que dividir o poema em linhas individuais.
  3. Você vai ter que pegar a primeira letra de cada linha.
    • Se a linha estiver vazia, você deve usar _ no lugar.
  4. Você vai ter que juntar as letras, que vão formar uma palavra.

Por exemplo, um dos escritores favoritos deles é Michael Lockwood, que escreveu o seguinte poema acróstico, o que significa que a primeira letra de cada frase forma uma palavra:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

Quando o guarda recitar o poema, você vai dividi-lo em linhas individuais e responder com as primeiras letras de cada linha, ou seja, ["S", "H", "I", "R", "E"].

O guarda então vai te dar a palavra formada pelo array de letras que você respondeu, para você colocá-la na forma de palavra com letras maiúsculas. Por fim, a senha que você retorna é "SHIRE", e você vai conseguir entrar.

Implemente a função frontDoorPassword, que recebe uma string que representa o poema. A função deve retornar a senha que você daria ao guarda.

frontDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "SHIRE"

3. Porta dos fundos

No fundo do clube você vai encontrar os poetas mais renomados, que é tipo a área VIP. Como isso não é para todo mundo, o processo da porta dos fundos é um pouco mais complicado.

  1. O guarda vai recitar um poema.
  2. Você vai ter que dividir o poema em linhas.
  3. Você vai ter que pegar a última letra de cada linha.
    • Às vezes a linha vai ter espaços no final, então você vai precisar removê-los.
  4. Você vai ter que juntar as letras e depois adicionar ", please" ao final da palavra formada pelas letras.

Por exemplo, o poema mencionado antes também é telestich, o que significa que a última letra de cada frase forma uma palavra:

Stands so high
Huge hooves too
Impatiently waits for
Reins and harness
Eager to leave

Quando o guarda recitar o poema, você vai dividi-lo em linhas individuais, remover os espaços no final e responder com as primeiras letras de cada linha, ou seja, ["h", "o", "r", "s", "e"].

O guarda então vai te dar a palavra formada pelo array de letras que você respondeu, para você colocá-la na forma de palavra com letras maiúsculas e acrescentar ", please". Por fim, a senha que você retorna é "horse, please", e você vai conseguir entrar.

Implemente a função backDoorPassword, que recebe uma string que representa o poema. A função deve retornar a senha que você daria ao guarda.

backDoorPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nReins and harness\nEager to leave")
// returns "horse, please"

4. Sala secreta

Dentro da sala dos fundos do clube há outra porta que leva à sala secreta, onde só os poetas mais importantes podem entrar.

  1. O guarda vai recitar um poema.
  2. Você vai ter que dividir o poema em linhas.
  3. Você vai ter que pegar a iésima letra da iésima linha.
  4. Você vai ter que juntar as letras e depois adicionar "!" ao final da palavra formada pelas letras.
  5. Você vai ter que colocar a palavra em letras maiúsculas.

Por exemplo, uma versão modificada do poema mencionado antes se encaixa nesse padrão:

Stands so high
Huge hooves too
Impatiently waits for
Rider with harness
Eager to leave

Quando o guarda recitar o poema, você vai dividi-lo em linhas individuais, remover os espaços no final e responder com as letras iésimas de cada linha, ou seja, ["S", "u", "p", "e", "r"].

O guarda então vai te dar a palavra formada pelo array de letras que você respondeu, para você colocá-la em letras maiúsculas e acrescentar "!". Por fim, a senha que você retorna é SUPER!, e você vai conseguir entrar.

Implemente a função secretRoomPassword, que recebe uma string que representa o poema. A função deve retornar a senha que você daria ao guarda.

secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
Editar via GitHub O link abre em uma nova janela ou aba
Swift Exercism

Tudo pronto para começar A 1ª Regra do Clube de Poesia?

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