Упражнения из лекций
Лекция 1. Введение в Swift и его экосистему
-
Установка и проверка. Установите Swift на свою систему Linux. Выполните команду
swift --versionи убедитесь, что вывод содержит номер версии Swift. -
Hello, World! Создайте файл
hello.swift, в котором программа выводит"Hello, World!". Скомпилируйте его с помощьюswiftcи запустите полученный бинарный файл. -
Визитная карточка. Напишите программу
card.swift, которая объявляет константы с вашим именем, возрастом и городом, а затем выводит их в формате:Имя: ИванВозраст: 20Город: МоскваИспользуйте интерполяцию строк (
\(переменная)). -
Калькулятор. Напишите программу
calc.swift, которая объявляет две целочисленные константыaиb, а затем выводит результаты сложения, вычитания, умножения и деления (целочисленного). -
REPL-эксперименты. Запустите Swift REPL (
swift) и выполните следующее:- объявите константу типа
String; - объявите переменную типа
Intи измените её значение; - попробуйте присвоить строку целочисленной переменной и изучите сообщение об ошибке.
- объявите константу типа
-
Сравнение с Python. Напишите одну и ту же программу (вывод таблицы умножения для числа 7) на Python и на Swift. Сравните синтаксис и процесс запуска.
Лекция 2. Переменные, константы и базовые типы данных
Задание 1. Переменные и константы
Объявите значения, выбрав let или var:
- Имя пользователя (не меняется)
- Текущий счёт в игре (меняется)
- Число Пи (не меняется)
- Текущая дата в формате строки (меняется)
Скомпилируйте через swiftc и убедитесь, что программа работает.
Задание 2. Преобразование типов
Объявите a: Int = 17 и b: Double = 3.0. Вычислите результат деления a на b (тип Double) и выведите через строковую интерполяцию.
Задание 3. Работа со строками
Создайте строку с полным именем. Выведите: количество символов, первый и последний символ, строку в верхнем регистре, результат проверки contains("ван").
Задание 4. Кортежи
Напишите функцию minMax(array:), возвращающую кортеж (min: Int, max: Int):
func minMax(array: [Int]) -> (min: Int, max: Int) { // ваш код}let result = minMax(array: [3, 1, 7, -2, 5])print("Мин: \(result.min), макс: \(result.max)")// Ожидаемо: Мин: -2, макс: 7Задание 5. Type Alias
Создайте typealias Student = (name: String, age: Int, grade: Double). Напишите функцию, принимающую [Student] и возвращающую средний балл.
Лекция 3. Операторы и управление потоком выполнения
- Калькулятор. Два числа и оператор (
+,-,*,/) — результат черезswitch. Обработайте деление на ноль. - Валидатор пароля. Функция
validatePassword(_ password: String?) -> Boolсguard: неnil, длина >= 8, есть цифра. - Оценка.
switchс диапазонами: 0–100 → «отлично» / «хорошо» / «удовл.» / «неуд.». - Фибоначчи. Первые 20 чисел через
while. - Чётные.
stride— чётные числа от 2 до 50. - Поиск пары. Первая пара
(i, j)из1...20, гдеi * j == 200, через labeledbreak.
Лекция 4. Функции и замыкания
Упражнение 1. Напишите функцию power(base:exponent:), которая возводит число в степень. Значение exponent по умолчанию — 2.
print(power(base: 3)) // 9print(power(base: 2, exponent: 10)) // 1024Упражнение 2. Напишите функцию joinStrings, принимающую вариативный параметр строк и разделитель (по умолчанию ", "), возвращающую объединённую строку.
print(joinStrings("Swift", "Python", "Go")) // Swift, Python, Goprint(joinStrings("a", "b", "c", separator: " - ")) // a - b - cУпражнение 3. Напишите функцию applyToEach, принимающую inout-массив [Int] и замыкание (Int) -> Int, применяющее преобразование к каждому элементу.
var nums = [1, 2, 3, 4, 5]applyToEach(&nums) { $0 * $0 }print(nums) // [1, 4, 9, 16, 25]Упражнение 4. Напишите makeMultiplier(factor:), возвращающую замыкание, умножающее число на factor.
let triple = makeMultiplier(factor: 3)print(triple(7)) // 21print(triple(10)) // 30Упражнение 5. Используя map, filter, reduce и trailing closure, обработайте массив 1…20: отберите числа, делящиеся на 3, возведите в квадрат, найдите сумму.
Лекция 5. Коллекции
Упражнение 1. Создайте массив целых чисел от 1 до 20. Используя filter и reduce, найдите сумму всех чисел, которые делятся на 3.
// Ожидаемый результат: 3 + 6 + 9 + 12 + 15 + 18 = 63Упражнение 2. Дан массив строк — названия городов. Используя map и sorted, получите массив строк вида "ГОРОД (N букв)", отсортированный по длине названия.
let cities = ["Москва", "Уфа", "Новосибирск", "Казань", "Сочи"]// Ожидаемый результат:// ["УФА (3 букв)", "СОЧИ (4 букв)", "КАЗАНЬ (6 букв)", "МОСКВА (6 букв)", "НОВОСИБИРСК (11 букв)"]Упражнение 3. Дано два множества Set<String> — навыки двух программистов. Найдите: (а) общие навыки, (б) уникальные навыки каждого, (в) все навыки вместе.
let dev1: Set = ["Swift", "Python", "Git", "SQL", "Docker"]let dev2: Set = ["Python", "JavaScript", "Git", "React", "Docker"]Упражнение 4. Создайте словарь [String: [Int]], где ключ — имя студента, значение — массив оценок. Используя map и reduce, создайте новый словарь [String: Double] со средними оценками.
let grades = [ "Анна": [90, 85, 92, 88], "Борис": [70, 65, 80, 75], "Виктор": [95, 100, 92, 98]]// Ожидаемый результат: ["Анна": 88.75, "Борис": 72.5, "Виктор": 96.25]Упражнение 5. Дан массив опциональных строк. Используя compactMap, извлеките непустые значения и преобразуйте их в верхний регистр.
let input: [String?] = ["swift", nil, "python", nil, "go", nil]// Ожидаемый результат: ["SWIFT", "PYTHON", "GO"]Упражнение 6. Напишите цепочку функциональных вызовов, которая из строки текста извлекает все слова длиной больше 4 символов, убирает дубликаты и возвращает отсортированный массив в нижнем регистре.
let text = "Swift это Swift язык для разработки приложений для Apple и Linux"// Ожидаемый результат: ["apple", "linux", "swift", "разработки", "приложений"]Лекция 6. Optionals — безопасная работа с отсутствием значений
Упражнение 1. Напишите функцию safeDivide(_ a: Double, _ b: Double) -> Double?, возвращающую результат деления или nil при делении на ноль.
print(safeDivide(10, 3) as Any) // Optional(3.3333...)print(safeDivide(10, 0) as Any) // nilУпражнение 2. Напишите функцию firstPositive(_ numbers: [Int]) -> Int?, возвращающую первое положительное число или nil.
print(firstPositive([-3, -1, 0, 4, 7]) as Any) // Optional(4)print(firstPositive([-3, -1, 0]) as Any) // nilУпражнение 3. Дан словарь [String: String] с данными пользователя. Напишите функцию greetUser, которая с помощью guard let извлекает "name" и "age" (преобразуя в Int), и выводит приветствие или сообщение об ошибке.
greetUser(["name": "Олег", "age": "22"]) // Привет, Олег! Тебе 22 лет.greetUser(["name": "Анна"]) // Ошибка: неполные данныеУпражнение 4. С помощью compactMap преобразуйте массив строк в [Double], затем найдите среднее через reduce.
let data = ["3.14", "abc", "2.71", "", "1.0"]// Ожидаемый результат: среднее ≈ 2.283Упражнение 5. Создайте структуры Company, Department, Employee с опциональными вложенными свойствами. Используя optional chaining и ??, безопасно получите имя сотрудника.
Лекция 7. Структуры и классы
Упражнение 1. Создайте структуру Temperature с хранимым свойством celsius: Double и вычисляемым свойством fahrenheit (с get и set). Формула: F = C × 9/5 + 32.
var temp = Temperature(celsius: 100)print(temp.fahrenheit) // 212.0temp.fahrenheit = 32print(temp.celsius) // 0.0Упражнение 2. Создайте структуру Vector2D с x, y: Double. Добавьте: вычисляемое свойство magnitude, mutating func scale(by:), статический метод static func add(_:_:) -> Vector2D.
Упражнение 3. Создайте класс Animal со свойствами name и sound. Присвойте один объект другому, измените свойство — убедитесь, что изменение отразилось на обоих. Повторите с аналогичной структурой и сравните.
Упражнение 4. Создайте структуру StepCounter со свойством totalSteps: Int с didSet, выводящим "Шагов добавлено: X. Всего: Y.".
var stepper = StepCounter(totalSteps: 0)stepper.totalSteps = 100 // Шагов добавлено: 100. Всего: 100.stepper.totalSteps = 360 // Шагов добавлено: 260. Всего: 360.Упражнение 5. Создайте класс LinkedNode с var value: Int и var next: LinkedNode?. Постройте цепочку из трёх узлов и пройдите по ней. Объясните, почему для связного списка необходим class, а не struct.
Лекция 8. Наследование и полиморфизм
Упражнение 1. Создайте иерархию Transport -> Car -> ElectricCar. Каждый класс переопределяет describe(). ElectricCar добавляет batteryLevel: Int.
Упражнение 2. Создайте BankAccount с designated и convenience инициализаторами. Дочерний SavingsAccount добавляет interestRate и метод addInterest().
Упражнение 3. Создайте массив фигур (Circle, Rectangle, Triangle). Используя is и as?, посчитайте количество каждого типа и выведите площади.
Упражнение 4. Создайте Logger с deinit. Продемонстрируйте вызов деинициализатора через блок do { }.
Упражнение 5. Перепишите на Swift с override и полиморфизмом:
class Notification: def __init__(self, msg): self.msg = msg def send(self): print(f"Уведомление: {self.msg}")
class EmailNotification(Notification): def __init__(self, msg, email): super().__init__(msg); self.email = email def send(self): print(f"Email на {self.email}: {self.msg}")
class SMSNotification(Notification): def __init__(self, msg, phone): super().__init__(msg); self.phone = phone def send(self): print(f"SMS на {self.phone}: {self.msg}")Лекция 9. Перечисления и Pattern Matching
Упражнение 1. Создайте перечисление Coin с вариантами kopeck(Int), ruble(Int), dollar(Int) (ассоциированное значение — номинал). Напишите функцию totalInRubles(_ coins: [Coin]) -> Double, которая считает общую сумму в рублях (курс доллара = 90.0).
Упражнение 2. Создайте enum MathOperation с case add(Double, Double), subtract(Double, Double), multiply(Double, Double), divide(Double, Double). Напишите функцию calculate(_ op: MathOperation) -> Result<Double, String>, возвращающую результат или ошибку при делении на ноль (используйте собственный Result).
Упражнение 3. Создайте indirect enum FileSystemItem с вариантами file(name: String, size: Int) и folder(name: String, contents: [FileSystemItem]). Напишите функцию totalSize(_ item: FileSystemItem) -> Int, рекурсивно вычисляющую суммарный размер.
Упражнение 4. Дан массив значений enum Weather:
enum Weather { case sunny(tempC: Double) case rainy(tempC: Double, mmPrecipitation: Double) case snowy(tempC: Double, cmSnow: Double) case cloudy}С помощью for case let ... where выведите только дождливые дни с осадками более 10 мм.
Упражнение 5. Создайте конечный автомат для состояния пользователя: guest, loggedIn(username: String), banned(reason: String). Реализуйте struct UserSession с методами login(username:), ban(reason:), logout(), проверяющими допустимость перехода через guard case.
Лекция 10. Протоколы и расширения
Упражнение 1. Создайте протокол Payable с требованиями:
- свойство
salary: Double { get } - метод
monthlyPay() -> Double
Реализуйте структуры FullTimeEmployee (ежемесячная выплата = salary / 12) и Contractor (ежемесячная выплата = salary * количество отработанных дней / рабочих дней). Создайте массив [Payable] и выведите информацию о каждом.
Упражнение 2. Создайте протокол Stackable с ассоциированными типами не используя — только методы push, pop, peek, isEmpty. Реализуйте структуру IntStack, соответствующую этому протоколу. Добавьте расширение с реализацией метода count.
Упражнение 3. Расширьте тип Double:
- вычисляемое свойство
km(конвертация километров в метры) - вычисляемое свойство
celsius(создаёт строку с «°C») - метод
roundTo(places:)— округление до указанного количества знаков
Упражнение 4. Создайте протокол Serializable с методом toJSON() -> String. Добавьте реализацию по умолчанию через расширение протокола. Реализуйте две структуры, одна из которых переопределяет метод toJSON().
Упражнение 5. Перепишите следующий Python-код на Swift с использованием протоколов и расширений:
from abc import ABC, abstractmethod
class Shape(ABC): @abstractmethod def area(self) -> float: ...
@abstractmethod def perimeter(self) -> float: ...
def describe(self) -> str: return f"Площадь: {self.area():.2f}, Периметр: {self.perimeter():.2f}"
class Circle(Shape): def __init__(self, radius: float): self.radius = radius
def area(self) -> float: import math return math.pi * self.radius ** 2
def perimeter(self) -> float: import math return 2 * math.pi * self.radius
class Square(Shape): def __init__(self, side: float): self.side = side
def area(self) -> float: return self.side ** 2
def perimeter(self) -> float: return 4 * self.side
shapes = [Circle(5), Square(3)]for s in shapes: print(s.describe())Упражнение 6. Создайте структуры Student и Course, соответствующие Equatable, Comparable, CustomStringConvertible и Hashable. Продемонстрируйте сортировку, поиск в Set и вывод через print().
Лекция 11. Обобщения (Generics)
Упражнение 1. Напишите обобщённую функцию filterItems<T>, принимающую массив [T] и замыкание (T) -> Bool, возвращающую массив элементов, удовлетворяющих предикату.
Упражнение 2. Создайте структуру Pair<A, B> с двумя значениями. Добавьте метод swapped() -> Pair<B, A>.
Упражнение 3. Реализуйте протокол Summable с associatedtype Element: Numeric и методом sum() -> Element. Реализуйте для структуры с массивом чисел.
Упражнение 4. Напишите removeDuplicates<T: Hashable>(from: [T]) -> [T] — массив без дубликатов с сохранением порядка.
Упражнение 5. Расширьте Stack<Element>: добавьте filter, а через where Element: Comparable — метод min() -> Element?.
Лекция 12. Обработка ошибок и управление памятью
Упражнение 1. Создайте enum ATMError: Error с кейсами insufficientFunds(required: Double), invalidPIN, cardBlocked. Напишите функцию withdraw(amount:pin:) throws, обработайте все ошибки в do-catch.
Упражнение 2. Напишите функцию divideAll(_ numbers: [Double], by divisor: Double) throws -> [Double], выбрасывающую ошибку при делении на ноль. Используйте try? и defer для логирования.
Упражнение 3. Создайте классы Author и Book с взаимными ссылками. Избегите retain cycle с помощью weak или unowned. Проверьте через deinit, что объекты освобождаются.
Упражнение 4. Создайте класс TaskRunner со свойством onComplete: (() -> Void)?. Продемонстрируйте утечку из-за захвата self в замыкании и исправьте её через [weak self].
Упражнение 5. Перепишите fetchUser(id:) из раздела 10, используя throws вместо Result. Сравните удобство обоих подходов.
Лекция 13. Конкурентность и асинхронное программирование
Упражнение 1. Напишите func delay(_ seconds: Double) async -> String, приостанавливающуюся на указанное время и возвращающую "Ожидание \(seconds) сек завершено". Вызовите с await.
Упражнение 2. С помощью async let запустите три вызова delay (1, 2 и 3 секунды) параллельно. Убедитесь, что общее время ~3 секунды, а не ~6.
Упражнение 3. Создайте func processItems(_ items: [String]) async -> [String] с withTaskGroup, параллельно переводящую строки в верхний регистр с имитацией задержки.
Упражнение 4. Напишите актор WordCounter со словарём [String: Int]. Метод count(word:) увеличивает счётчик, topWords(n:) возвращает n самых частых слов. Тестируйте из нескольких задач.
Упражнение 5. Реализуйте кооперативную отмену: задача обрабатывает массив с Task.checkCancellation(), отмените её через 0.3 секунды.
Упражнение 6. Перепишите упражнение 3 с withThrowingTaskGroup: строки короче 3 символов должны вызывать ошибку.
Лекция 14. Экосистема Swift и итоговый проект
Упражнение 1. Создайте Swift-пакет Greeting с функцией greet(name: String) -> String. Напишите тест, проверяющий результат. Запустите swift build и swift test.
Упражнение 2. Напишите CLI-утилиту, принимающую путь к JSON-файлу и выводящую его в отформатированном виде. Используйте Foundation и JSONSerialization.
Упражнение 3. Создайте Codable-структуру Config с полями host, port, debug. Реализуйте чтение из JSON-файла, обработайте ошибки через do-catch без force unwrapping.
Упражнение 4. Перепишите любой Python-скрипт на Swift. Сравните читаемость и типобезопасность.
Упражнение 5. Создайте Vapor-сервер с маршрутами GET /, GET /time, POST /echo. Протестируйте через curl.