Треки
/
Swift
Swift
/
Вправи
/
Перше правило клубу поезії
Перше правило клубу поезії

Перше правило клубу поезії

Навчальна вправа

Вступ

Імпортування

Хоча Swift надає багато функціональності у своїй стандартній бібліотеці, багато додаткових можливостей можна отримати, імпортуючи зовнішні бібліотеки та фреймворки. Ці модулі можуть походити безпосередньо від проєкту Swift (як-от Swift Argument Parser), від фреймворків платформи Apple (як-от Foundation і Network Framework) або від сторонніх бібліотек з відкритим кодом (як-от SwiftyBeaver).

Основні модулі, як-от Foundation, одна з найуживаніших бібліотек у Swift, входять до складу інструментарію Swift. Сторонні бібліотеки потрібно додати до конфігурації проєкту (наприклад, скориставшись Swift Package Manager), перш ніж їх можна буде імпортувати.

Імпортування модулів відбувається так: пишемо ключове слово import, а потім назву модуля. Тож щоб імпортувати Foundation, достатньо додати до своєї програми таке.

import Foundation

Імпортування модуля робить його типи, методи й функції доступними для нашого коду. Наприклад, імпорт Foundation розширює String корисними допоміжними методами, як-от components(separatedBy:).

За домовленістю інструкції import ставлять на початку файлу Swift, щоб залежності було відразу видно кожному, хто читає код.

Індексування рядків

Окремі символи в String можна отримати тим самим способом індексування, який використовують для масивів. Однак індекси, які використовують для рядків тексту (англ. string), не є цілими числами, і працювати з ними безпосередньо не можна. Замість цього їх потрібно обчислити на основі якогось іншого відомого індексу, наприклад startIndex, який указує на позицію першого символу в непорожньому рядку тексту, скориставшись методами, доступними в бібліотеках String та NSString (коли модуль Foundation імпортовано, рядки тексту у Swift мають доступ до всіх властивостей і методів NSString).

Наприклад, маємо такий рядок тексту:

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

Не можна написати csv[21], щоб отримати "g" в "orange": замість цього потрібно обчислити значення типу String.Index і передати саме його. Зауважмо, що ці індекси не призначені для безпосереднього сприйняття людиною. Їх називають непрозорими індексами, бо людині не потрібно знати, що всередині них.

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

Проте зауважмо: якщо зсув не відповідає дійсному індексу, тобто якщо він указує на позицію перед startIndex або після endIndex, операція спричинить помилку й аварійно завершить програму. Щоб запобігти цій проблемі, можна вказати обмежувальний індекс. Тоді операція повертає необовʼязковий індекс і поверне nil для індексів, які інакше були б недійсними.

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

Крім того, індекси не можна використовувати для різних рядків тексту. Наприклад, якщо скористатися обчисленим вище index для "g" в "orange", щоб проіндексувати рядок fam = "This is my family: 👨‍👩‍👦‍👦, this is our dog: 🐶, this is our cat: 🐱!", тобто fam[index], програма аварійно завершиться.

Для всього цього є багато причин, але всі вони зводяться до того, що «з Unicode усе непросто».

Загалом, якщо потрібен довільний доступ до окремих символів, імовірно, варто використати якусь іншу структуру даних, як-от Array<Character>.

Деякі корисні методи

У Swift є методи first і last, щоб отримати перший і останній символ рядка тексту. Ці методи повертають необовʼязковий символ, тож якщо рядок тексту порожній, вони повернуть nil.

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

Також можна скористатися методами prefix і suffix, щоб отримати підрядок рядка тексту. Ці методи приймають ціле число як аргумент і повертають підрядок, що містить перші або останні n символів рядка тексту.

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

Методи рядків

Робота з текстом трапляється в програмуванні часто. Swift разом із фреймворком Foundation надає багато зручних методів і властивостей для перегляду, перетворення й опрацювання рядків тексту.

Розбиття рядків тексту за допомогою components(separatedBy:)

Щоб розбити рядок тексту на масив підрядків за розділювачем, можна скористатися методом components(separatedBy:) (потрібен імпорт Foundation):

import Foundation

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

Перевірка префіксів і суфіксів за допомогою hasPrefix(_:) і hasSuffix(_:)

Щоб перевірити, чи рядок тексту починається або закінчується певною послідовністю символів, можна скористатися методами hasPrefix(_:) і hasSuffix(_:):

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

Зміна регістру

Змінити регістр рядка тексту можна за допомогою цих стандартних методів і властивостей:

  • lowercased(): повертає копію рядка тексту в нижньому регістрі.
  • uppercased(): повертає копію рядка тексту у верхньому регістрі.
  • capitalized: повертає копію, у якій першу літеру кожного слова записано з великої літери (з Foundation).
let greeting = "hello, world!"
print(greeting.lowercased())  // Prints "hello, world!"
print(greeting.uppercased())  // Prints "HELLO, WORLD!"
print(greeting.capitalized)   // Prints "Hello, World!"

Заміна підрядків за допомогою replacingOccurrences(of:with:)

Щоб замінити всі входження цільового підрядка на інший рядок тексту, можна скористатися методом replacingOccurrences(of:with:) (з Foundation):

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

Зʼєднання рядків за допомогою joined(separator:)

Метод joined(separator:) належить колекціям рядків тексту, як-от [String]. Він поєднує елементи в один рядок тексту за допомогою розділювача:

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

Вказівки

У місті відкрився новий поетичний клуб, і ми думаємо, чи не завітати туди. Оскільки в минулому траплялися інциденти, у клубу дуже специфічні правила входу, які потрібно опанувати, перш ніж намагатися зайти.

У поетичному клубі є двоє дверей, і обидві охороняються. Щоб потрапити всередину, потрібно розгадати пароль на цей день:

1. Розбити рядок тексту на окремі рядки

Перше, що потрібно зробити, - розбити вірш на окремі рядки. Охоронець прочитає вірш, а нам потрібно буде розбити його на рядки.

Реалізуйте функцію splitOnNewlines, яка приймає рядок тексту (англ. string) і розбиває його на масив рядків тексту, використовуючи символ нового рядка як розділювач. Функція повинна повернути масив рядків тексту, де кожен елемент - це один рядок вірша.

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

2. Парадний вхід

  1. Охоронець прочитає вірш
  2. Потрібно буде розбити вірш на окремі рядки.
  3. Потрібно буде взяти першу літеру кожного рядка.
    • Якщо рядок порожній, замість літери слід використати _.
  4. Потрібно буде зібрати літери, і вони утворять слово.

Наприклад, один з їхніх улюблених письменників - Майкл Локвуд, який написав такий акровірш, а це означає, що перша літера кожного речення утворює слово:

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

Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки та відповідаємо першими літерами кожного рядка, тобто ["S", "H", "I", "R", "E"].

Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати з великої літери. Зрештою пароль, який ми повертаємо, - це "SHIRE", і ми потрапляємо всередину.

Реалізуйте функцію frontDoorPassword, яка приймає рядок тексту, що представляє вірш. Функція повинна повернути пароль, який ми назвемо охоронцеві.

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

3. Чорний хід

У глибині клубу збираються найвідоміші поети, щось на кшталт VIP-зони. Оскільки це не для всіх, вхід через чорний хід трохи заплутаніший.

  1. Охоронець прочитає вірш.
  2. Потрібно буде розбити вірш на рядки.
  3. Потрібно буде взяти останню літеру кожного рядка.
    • У рядку іноді трапляються пробіли в кінці, тож їх потрібно прибрати.
  4. Потрібно буде зібрати літери, а потім додати ", please" у кінець слова, утвореного з цих літер.

Наприклад, згаданий вище вірш - це також телестих, а це означає, що остання літера кожного речення утворює слово:

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

Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки, прибираємо пробіли в кінці та відповідаємо останніми літерами кожного рядка, тобто ["h", "o", "r", "s", "e"].

Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати з великої літери та додати ", please". Зрештою пароль, який ми повертаємо, - це "horse, please", і ми потрапляємо всередину.

Реалізуйте функцію backDoorPassword, яка приймає рядок тексту, що представляє вірш. Функція повинна повернути пароль, який ми назвемо охоронцеві.

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

4. Таємна кімната

У глибині клубу є ще одні двері, які ведуть до таємної кімнати, куди можуть зайти лише найкращі поети.

  1. Охоронець прочитає вірш.
  2. Потрібно буде розбити вірш на рядки.
  3. Потрібно буде взяти i-ту літеру i-го рядка.
  4. Потрібно буде зібрати літери, а потім додати "!" у кінець слова, утвореного з цих літер.
  5. Потрібно буде записати слово великими літерами.

Наприклад, змінений варіант згаданого вище вірша відповідає цій схемі:

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

Коли охоронець прочитає вірш, ми розбиваємо його на окремі рядки, прибираємо пробіли в кінці та відповідаємо i-ми літерами кожного рядка, тобто ["S", "u", "p", "e", "r"].

Тоді охоронець назве слово, утворене з масиву літер, якими ми відповіли, і це слово потрібно буде записати великими літерами та додати "!". Зрештою пароль, який ми повертаємо, - це SUPER!, і ми потрапляємо всередину.

Реалізуйте функцію secretRoomPassword, яка приймає рядок тексту, що представляє вірш. Функція повинна повернути пароль, який ми назвемо охоронцеві.

secretRoomPassword("Stands so high\nHuge hooves too\nImpatiently waits for\nRider with harness\nEager to leave")
// returns "SUPER!"
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Swift Exercism

Час розпочати Перше правило клубу поезії?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Swift, а також 35 концепцій116 вправ та справжнє наставництво від людей, і все це безкоштовно.