Разбор задачи D отборочного этапа Yandex Cup 2023 — iOS

Предисловие

Эта статья из серии с разбором задач отборочного этапа Yandex Cup 2023 по направлению iOS-разработка с призовым фондом почти в 9 000 000 рублей. Повторюсь, правильных ответов у меня не было, и решал я уже после окончания отборочного этапа. Если заметите какие-либо неточности в формулировках, в размышлениях, в ответах, буду рад обсудить это в комментариях.

Начнем!)

Условие

Пример кода

enum ColorComponent {
  case red
  case green
  case blue
}

Известно, что код работает правильно, если enum ColorComponent сможет содержаться в Set. Ваша задача определить, сработает ли код, или понять, что нужно сделать, чтобы его исправить

Варианты ответов

  1. Добавить соответствие протоколу Hashable

  2. Добавить соответствие протоколу Equatable

  3. Добавить соответствие протоколу Comparable

  4. Ничего дополнительно делать не надо

  5. Enum не может содержаться в Set

Мой итоговый ответ

Спойлер

  1. Ничего дополнительно делать не надо

Решение

Для решения данной задачи необходимо понять какие условия должны выполняться элементами, которые мы хотим поместить в контейнер Set. Для этого обратимся к документации:

You can create a set with any element type that conforms to the Hashable protocol. By default, most types in the standard library are hashable, including strings, numeric and Boolean types, enumeration cases without associated values, and even sets themselves.

Во-первых, мы узнали, что условие, которое должно выполняться элементами, помещаемыми в Set — это соответствие протоколу Hashable. В то же время, нужно помнить, что протокол Hashable соответствует протоколу Equatable, об этом написано в документации:

Но в идеале, конечно, не зубрить документацию, а потратить немного времени и понять зачем так было сделано. Ничего сложного тут нет, одна из причин того, что протокол Hashable соответствует протоколу Equatable, заключается в том, что при проверке на принадлежность объекта к множеству, мы должны по каким-то признакам определять равенство элементов, чтобы понимать содержится наш элемент во множестве или нет. К примеру, мы хотим добавить новый элемент в контейнер, но по его хэшу уже содержится какое-то значение. Собственно, нам нужно проверить — равен ли добавляемый элемент тому, что уже находится по данному хэшу. Если да, то мы ничего не делаем, в противном случае произошла коллизия (разные объекты имеют одинаковое хэш-значение) в конец односвязного списка по данному хэшу добавится новый объект. А сама логика связанная с хэшированием объектов реализована в структуре Hasher:

Во-вторых, так как наше перечисление не имеет ассоциативных значений, это означает, что оно по умолчанию подписано и реализует протокол Hashable (и в то же время протокол Equatable, как мы разобрались выше). Вы можете подумать, что значениям enum-а по умолчанию задаются целочисленные значения, как в языках С, C++ и Objective-C, а в свою очередь целочисленный тип Int соответствует протоколу Hashable, и по этой причине нам не нужно явно указывать соответствие данному протоколу, но на самом деле тут не все так просто. В языке Swift case-ы перечисления самостоятельны и в текущем примере их типом является ColorComponent.

Особо пытливым предлагаю ознакомиться с документацией языка Swift, там вы сможете более детально разобраться, как все устроено «под капотом» (напишите, пожалуйста, в комментариях или в личные сообщения, если бы вам хотелось видеть еще более глубокий разбор различных инструментов языка, в этом случае я учту это при написании следующих статей):

GitHub — apple/swift: The Swift Programming Language

github.com

Разбор ответа №1 (Добавить соответствие протоколу Hashable)

Добавлять соответствия протоколу Hashable не нужно, так как по умолчанию наше перечисление уже соответствует данному протоколу.

Разбор ответа №2 (Добавить соответствие протоколу Equatable)

Добавлять соответствия протоколу Equatable не нужно, так как по умолчанию наше перечисление уже соответствует протоколу Hashable, который соответствует протоколу Equatable.

Разбор ответа №3 (Добавить соответствие протоколу Comparable)

Так как Set в языке Swift представляет из себя неупорядоченную коллекцию уникальных элементов, нам необязательно указывать соответствие протоколу Comparable, но в то же время мы будем обязаны это сделать, если захотим реализовать упорядоченную коллекцию уникальных элементов (Ordered Set).

Разбор ответа №4 (Ничего дополнительно делать не надо)

Данный ответ является верным, в пункте «Решение» приведено объяснение.

Разбор ответа №5 (Enum не может содержаться в Set)

Данный ответ является неверным, в пункте «Решение» приведено объяснение.

Итог

Важно помнить о том, какие условия должны выполняться определенными объектами, чтобы они могли быть помещены в различные коллекции. В самом языке имеется довольно-таки большое количество контейнеров, которые можно использовать для решения различных задач. Наиболее популярными, конечно же, являются String, Set, Dictionary, Array, но хотелось бы упомянуть и чуть менее известные, такие как: Bit Set (для реализации необходимо указать соответствие протоколуOptionSet), Range.

Подводя итоги, хотелось бы поблагодарить следующих людей за помощь в подготовке данной статьи:

d5ecf34b99ffa3899c7e205bb3253ef8.pngГригорий С.

Senior iOS-developer

e13875c72acfb41f12267162af5d37bc.jpegЕгор Н.

Senior iOS-developer | Team Lead

© Habrahabr.ru