Яндекс: о компании, работе, устройстве, тестах и собеседовании

Третья секция

Третья секция называлась “Алгоритмы”. Я ожидала алгоритмы-алгоритмы (сортировку слиянием, отличия O-нотации от тета-нотации и описание работы машины Тьюринга), но нет. То ли фронтендеров так не мучают, то ли вообще людей так не мучают, но задачи были не на алгоритмы как таковые, а на обычную логику.

Проводил секцию молодой человек, занимающийся в компании рекламой. Свыше 90% прибыли компании приносит реклама, вот собственно таргетированной рекламой он и занимается.

Здесь я по сути решала одну и ту же задачу трижды. Задачу можно назвать “Банкомат”. Вроде бы дважды я ее решила, а вот третий раз решить не успела (или не шмогла), как раз сейчас сижу и собираю все мысли по этому поводу, которые есть.

Задача была — выдать деньги. Условие минимального количества купюр не ставилось, просто выдать, но желательно максимальными купюрами.

Первая итерация задачи:

var moneyTypes = ;function getMoney(amount) {   // нужно вернуть набор денег в следующем формате   // {   //   5000: 1,   //   1000: 2,   //   ....   //   50: 5   // }   // Или бросить исключение, если вернуть деньги невозможно}

Вторая итерация задачи включала лимиты:

var limits = {  5000: 4,  1000: 5,  500: 2,  100: 5,  50: 100};function getMoney(amount, limits) {   // нужно вернуть набор денег и обновленные лимиты   // {   //   res: {   //     5000: 1,   //     1000: 2,   //     ....   //     50: 5   //   } || "warn" (если вернуть деньги невозможно)   //  limits: // объект лимитов той же структуры с обновленными    данными   // }}

И третья итерация была с такими лимитами:

var limits = {  5000: 4,  1000: 5,  500: 2,  100: 5,  50: 100,  30: 23};

Здесь просто идти в лоб от наибольшего значения к наименьшему нельзя, т.к. в лоб я не смогу вернуть значение 120, которое можно соорудить из 30-к. А идти от наименьшего нельзя по условию задачи (да и не должен банкомат выдавать деньги мелкими купюрами).

Вот сейчас сижу и думаю как ее решить. Пока что надумала только вариант выстроить объект лимитов в нечто древовидное и ходить последовательно по возможным веткам дерева, если попытка набрать денег по предыдущей ветке не увенчалась успехом. Но это пока только мысль-набросок, надо попытаться реализовать ее и погуглить, как это умные люди вообще делают.

E. Анаграммы

Ограничение времени 1 секунда
Ограничение памяти 20Mb
Ввод стандартный ввод или
Вывод стандартный вывод или

Даны две строки, состоящие из строчных латинских букв. Требуется определить, являются ли эти строки анаграммами, т. е. отличаются ли они только порядком следования символов.

Формат ввода

Входной файл содержит две строки строчных латинских символов, каждая не длиннее 100 000 символов. Строки разделяются символом перевода строки.

Формат вывода

Выходной файл должен содержать единицу, если строки являются анаграммами, и ноль в противном случае.

F. Слияние k сортированных списков

Язык Ограничение времени Ограничение памяти Ввод Вывод
Все языки 1 секунда 10Mb стандартный ввод или стандартный вывод или
Oracle Java 7 1 секунда 20Mb
Node JS 8.9.4 1 секунда 20Mb
Oracle Java 8 1 секунда 20Mb
Kotlin 1 секунда 20Mb

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

Длина каждого массива не превосходит 10 ⋅ k.

Постарайтесь, чтобы решение работало за время k ⋅ log(k) ⋅ n, если считать, что входные массивы имеют длину n.

Формат ввода

Первая строка входного файла содержит единственное число k, k ≤ 1024.

Каждая из следующих k строк описывает по одному массиву. Первое число каждой строки равняется длине соответствующего массива, оставшиеся числа этой строки описывают значения элементов этого же массива. Элементы массивов являются неотрицательными целыми числами и не превосходят 100.

Формат вывода

Выходной файл должен содержать отсортированный в порядке неубывания массив, содержащий все элементы исходных массивов.

FAQ по контесту

A: Я точно написал правильный код, но тесты не проходят; наверное, в них ошибка?
Q: Нет, все тесты правильные. Подумайте: вероятно, вы не предусмотрели какую-нибудь необычную ситуацию.

A: Я пишу на языке X, ему точно требуется больше памяти в задаче Y. Поднимите лимиты!
Q: Все лимиты выставлены таким образом, что решение возможно с использованием любого из доступных языков. Попробуйте проверить, не зачитываете ли вы случайно входной файл целиком в задачах со строгими лимитами по используемой памяти.

A: Некоторые задачи можно решить намного проще из-за указанных ограничений. Зачем вы так?
Q: Мы специально упростили ввод в некоторых задачах, чтобы участникам было проще сосредоточиться на реализации алгоритма и не думать, например, о скорости загрузки данных или каких-то других вещах, важных в спортивном программировании. Постарайтесь реализовать именно те алгоритмы, которые мы рекомендуем — только в такой ситуации вы получите от контеста максимальную пользу.

A: Не хочу проходить контест. Можно я не буду?
Q: Конечно! Контест не является обязательным к решению всеми кандидатами. Впрочем, я всё равно рекомендую его порешать: это в любом случае будет полезно.

A: Что ещё посоветуете для подготовки?
Q: Прочитайте наши советы на официальной странице про собеседования в Яндекс: https://yandex.ru/jobs/ya-interview. От себя добавлю, что решение задачек на leetcode.com является крайне полезным для любого практикующего разработчика, независимо от того, планирует ли он в ближайшее время проходить интервью или участвовать в соревнованиях по программированию. Даже небольшое количество практики позволяет почувствовать себя увереннее при решении рабочих задач.

Развитие способов защиты

Вообще, если говорить про тренды, сейчас отмирают и, думаю, окончательно отомрут многие вещи, которые нам до последнего казались классическими, обязательными. Например, DLP (защита от утечек). В современном мире использовать ее уже нереально. Внедряя DLP, ты обманываешь себя. Да, с ней можно поймать сотрудника, который по почте что-то не то отправил, но защититься от целенаправленного выноса данных с ней невозможно. Пока еще на DLP все смотрят как на обязательную вещь в компаниях «классического» уклада. Когда же интернет проникнет еще глубже, такие меры безопасности вчерашнего дня, как DLP, окончательно отомрут.

Вторая вещь, которая меняет парадигму безопасников, — это облачные инструменты. Причем сейчас я говорю не про структуры в облаке, все гораздо проще.

Как правило, проблемы случаются из-за каких-то мелких глупостей. Конечно, может, под тебя пятнадцать лет АНБ подкапывается, но гораздо раньше проблемы у тебя возникнут совсем по другой причине. Они произойдут, когда кто-то зальет коммерческую информацию куда-нибудь, просто не зная, что она сохраняется в облаке.

Поясню. Несколько лет назад мне нужен был «блокнот». Меня не устраивал стандартный маковский Notes, и я искал что-то получше. И я не смог найти в App Store ни одного необлачного! В том же Evernote, например, сначала была опция хранения в облаке как opt-in (ее надо было включить). Сейчас это опция opt-out (ее нужно найти и самому выключить). Причем она так запрятана, что 9 из 10 скачавших о ней просто не узнают. С точки зрения безопасности вот такие тривиальные вещи гораздо более рисковые.

Свежий пример: взлом Uber и то, как у них украли миллионы учетных записей. Там ведь никто не ломал сам сервис. Ситуация глупая: разработчик на GitHub держал свой не Uber’овский код, и у него в этом коде были зашиты логин и пароль. Просто лежали в public, а логин-пароль оказался такой же, как и от его учетной записи в компании. Uber в Amazon держал свои бэкапы, а этот логин и пароль подошли. Вот так «хакер» зашел, попробовал — подошло, и миллионы учеток утекли. В реальной жизни инциденты чаще происходят не из-за «продвинутых угроз», а по таким вот мелочам.

То есть уровни безопасности размылись. Подчас даже не отдаешь себе отчет: что ты используешь в облаке, что доступно снаружи. Современная работа идет в размытом периметре. Сам периметр — это уже вещь прошлого века. Сейчас у всех так. Если ты занимаешься бизнесом, который взлетает, то ты уже не покупаешь сервак и даже не арендуешь его. Вместо этого ты поднимаешь виртуалочку в Amazon и облачное хранилище. У тебя все там, а потом какой-нибудь сотрудник использует свой домашний пароль как рабочий и случается утечка.

Алгоритмические секции и спортивное программирование

Спортивное программирование развивает в будущем разработчике, помимо прочего, и способность быстро и без ошибок реализовывать простые алгоритмы согласно заранее назначенному плану. Поэтому кандидаты с опытом спортивного программирования, действительно, неплохо справляются с алгоритмическими секциями на собеседованиях. Часто можно наблюдать ситуацию, когда будущие стажёры легко справляются с алгоритмической секцией, решая все задачи за 15-20 минут, тогда как более опытные программисты на те же задачи тратят целый час.

В то же время, алгоритмическая секция с написанием кода — лишь одна из секций, проверяющая минимально необходимые для любого разработчика навыки. С этой секцией справятся не только олимпиадные программисты, но и опытные промышленные разработчики. Будущего старшего разработчика или руководителя группы обязательно ждёт архитектурная секция, на которой он сможет раскрыть свои самые сильные стороны; конечно, эта секция никогда не ставится стажёрам и младшим разработчикам.

Первая секция

На первой секции со мной общался паренек, занимающийся в поиском по картинкам.

Его вопросы, которые я помню:

  1. Написать функцию getPrimes(n) // Должна вернуть простые числа от 2 до n;
  2. Написать функцию, проверяющую правильно расставленные скобки;
check("{()}[]") // truecheck("{") // false

3. Написать функцию sum чтобы выражение возвращало 17.

4. Написать функцию getAnagrams

Должна вернуть

,  ]

5. Рассказать что знаешь про методы оптимизации веб-страницы.

6. Рассказать про ограничения кроссдоменных запросов.

7. Рассказать про то, что проиходит от момента вбивания адреса в адресную строку браузера до момента полной отрисовки страницы.

Яндекс как большой дом

В Яндексе я дома, со всеми вытекающими отсюда плюсами. Сейчас много людей уезжает из России на Запад, но мало кто остается там на всю жизнь. Едут в основном молодые, которые хотят посмотреть, попробовать. Некоторые, конечно, остаются, но отъезд на Запад для айтишников, мне кажется, не самоцель. Это не переезд в Америку или в Лондон. Они едут в крупные ИТ-компании, уезжают работать в Facebook, Google, Amazon. Все остальное — это уже побочные эффекты. Кстати, айтишнику проще адаптироваться на Западе. Просто потому, что многие айтишники сидят за компом по 24 часа в сутки, игнорируют языковые и культурные барьеры, так как особо не ведут социальную жизнь.

Яндекс — это место, где ты можешь получить все то же самое в плане интересных задач, работы с данными и сложными системами, попробовать машинное обучение и другие современные технологии. При этом ты остаешься у себя дома, в России.

Технократия и единство технологий

Яндекс привлекает еще и тем, что в нем отсутствует излишняя бюрократия. Как следствие — есть возможность быстрее и эффективнее обучаться. Если сравнивать с теми же Google и Facebook, я бы сказал, что у нас бюрократии нет вообще. Есть технократия, и вот в чем она проявляется. Яндекс все-таки сильно вырос. Когда людей становится больше, то контролировать их собственную эффективность сложнее. Но порог входа у нас высокий, и мы понимаем, что если кто-то неэффективно работает, то это, скорей всего, потому, что к человеку не нашли подхода, а не потому, что он неспособен. Нужно задать ему правильный вектор развития.

Вектор — это тоже свобода, но не абсолютная, не мешающая другим. К примеру, ты не можешь сказать, что тебе не нравится принятая система обработки логов на внутреннем MapReduce и сейчас ты поднимешь свой Hadoop. Или ты не можешь писать на Rust просто потому, что так захотел. Хочешь использовать другие языки? Пожалуйста, но только в свободное время в качестве хобби. В основных же проектах есть перечень утвержденных языков программирования. Он нужен для того, чтобы проекты можно было поддерживать дальше, когда ими займутся другие программисты. По той же причине у нас есть единый репозиторий, и никто не хранит код «в тумбочке».

Здесь, в Яндексе, ты делаешь продукт, который потом кто-то должен поддерживать за тобой. Поэтому нужно соблюдать единство IT-технологий, использовать общую платформу развертывания и так далее. Словом, вместо бюрократии в Яндексе царит технократия.

E. Анаграммы

Для решения этой задачи будем подсчитывать сколько раз в каждой строке встречается та или иная буква и сравнивать полученные результаты. Сразу понимаем, что стандартные списки нам не подходят, и необходимо использовать структуру данных, которая бы позволила эффективно обращаться к элементу по его индексу. Существует несколько типов данных, которые бы удовлетворяли нашим условиям, мы же воспользуемся стандартным неизменяемым массивом Data.Array (ещё существуют как минимум различные изменяемые массивы, а также Data.Vector).

Для конструирования необходимых массивов воспользуемся функцией hist :: (Ix a, Num b) => (a,a) -> -> Array a b, которая по переданному списку элементов и диапазону, которому данные элементы должны принадлежать, формирует массив, который хранит в себе количество повторов элементов из списка. Данная функция хоть и не входит в модуль Data.Array, но часто приводится как пример использования другой, уже библиотечной функции accumArray. Нам остаётся только скопировать её реализацию и написать main – благо сравнение на равенство для Array Char Int уже определено

Обращаю ваше внимание на одну приятную особенность – в качестве индекса мы можем воспользоваться не только целыми числами, а любым представителем класса Ix. В нашем случае на эту роль естественным образом подходит Char

Зачем писать код на доске или бумаге

Естественное состояние для программиста — программирование в интегрированной среде разработки с подсветкой синтаксиса и возможностью трассировки. Поэтому идея на собеседовании писать код на доске или бумаге первоначально кажется не слишком естественной. Однако, этот способ позволяет проверить два очень важных для каждого разработчика свойства.

Первое из них — умение быстро разбираться с работоспособностью кода «на глаз». Представьте себе, что при написании каждого цикла, возникающего в программе, разработчику требуется потратить время на то, чтобы проверить его работоспособность трассировкой; или что при падении сервиса в продакшене ему всегда обязательно нужно запустить код под дебаггером. Ясно, что написание и отладка даже несложных программ будут занимать у него непозволительно много времени. Конечно, полезно уметь читать код и при код-ревью.

Второе важное свойство — способность заранее продумывать план решения и затем следовать ему. Если плана нет, это будет приводить к большому количеству исправлений, зачёркиваний (на бумаге) и переписыванию больших кусков кода

В реальной жизни всё это сильно замедляет разработку, но отчасти маскируется скоростью работы в редакторе кода. Доска и бумага в этом смысле являются беспощадными поверхностями.

Естественно, мы учитываем, что писать код от руки — не слишком быстрое дело. Поэтому наши задачи обычно предполагают решение не намного длиннее десятка строк, а количество задач, которые необходимо решить в течение одной секции, обычно равняется двум или трём.

Четвертая секция

Четвертая секция оказалась самой суровой. Или программист там был самый суровый, или я уже слабо соображала к четвертому часу. Я даже не помню, чем этот суровый программист занимается в компании. Но помню вопросы на которых я жутко тупила. Вроде решила все, но настолько криво и медленно, что ужас.

Собственно секция была посвящена JavaScript и написанию кода на бумаге.

  1. Реализовать функции , чтобы работало:
five(add(one())) // 6seven(subtract(two())) // 5

2. Написать функцию myNew, чтобы она работала как конструктор, но без вызова new.

function Person(name, age) {  this.name = name;  this.age = age;}var person = myNew(person, "Vasia", 34);person instanceOf Person // true;

3. Найти сумму всех values

{  value: 4,  next:     },    {      value: 3,      next:     },    ...  ]}

Вроде это все задачи, которые я помню, процентов 80 я описала. Было что-то еще, что вылетело из головы.

Безопасность в разработке

Ключевые слова для описания безопасности в такой компании, как Яндекс, — это автоматизация и интеграция. К примеру, ты написал приложение для Android и тебе нужно подписать приложение ключом разработчика. Ты не хранишь ключ у себя. У нас для этого есть сервис, который сделали безопасники. Он называется «Подписатор». Ты присылаешь туда свой файл, он подписывается и там же проходит основные проверки на безопасность. Обратно ты получаешь уже проверенный и подписанный файл.

Обычно как происходит? Программист пишет код, а потом в него добавляют средства безопасности. То есть ты пришел на работу, тебе сказали: вот твоя поляна — пиши. Ты ничего не знаешь о том, что делают безопасники, пока тебе не падает письмо: у тебя вот здесь в программе уязвимость, пожалуйста, исправь ее.
Мы стараемся, чтобы работа строилась по-другому, но старания начинаются не с момента написания кода, а еще раньше.

Как это выглядит в идеале. Ты пришел на работу, прошел собеседование (несколько секций с разными людьми). Одна из секций — собеседования про безопасность. Она не будет определяющей, потому что берут программиста, а не безопасника, но нам падает информация, что пришел такой-то человек и он плохо ответил на вопросы о безопасности. Это потенциальная проблема для нас в будущем. Тогда ему в рамках стандартного введения дают правила безопасной разработки, какие-то дополнительные кейсы, которые у нас есть. То есть мы начинаем думать о безопасности на уровне обучения, еще до того, как программист напишет свою первую строчку кода.

Дальнейшая безопасность затрагивает инструменты, которыми ты пользуешься. Есть такое популярное слово — SDL (Security Development Lifecycle), которое придумала и которому дала широкое распространение Microsoft. У нас взяты какие-то основные куски от SDL. Мы берем компоненты, которые важны для нас, и внедряем их.

К примеру, ты взял для своего проекта какую-то библиотеку, содержащую уязвимость. Тебя не бьют по рукам, но, когда ты закоммитишь свой код, сработают автоматические проверки. Они скажут, что ты притащил фигню, лучше возьми вот это. Финальный шаг — аудит твоего кода, причем аудит кода в рамках всего продукта. Его будет смотреть команда безопасников.

Не числом, а умением!

Яндекс обычно сравнивают с такими компаниями, как Facebook и Google, но у нас есть важное отличие. Яндекс — это компания, которая со штатом в 5–7 тысяч человек делает такие же штуки, как западные компании со штатом в 50–60 тысяч человек

Это результат хорошего образования, более глубокого знания математики и подготовки более универсальных программистов.

То есть надо понимать, с кем и в каких условиях нам приходится конкурировать. У Facebook, например, по сути, есть один сервис и одно приложение. Нет «зоопарка» и сложной экосистемы, но людей задействовано раз в десять больше, чем в Яндексе.

Это момент, который, мне кажется, многие не понимают. Здесь, в Яндексе, гораздо выше концентрация всего: больше разных задач и свободы для программиста. Ты можешь сам выбирать, чем заниматься.

В Google, например, уже сложились рабочие процессы, и тебя берут на конкретную очень узкую задачу. Условно говоря, представь, что ты занимаешься перекладыванием бумажек с места на место. Тебе за это платят деньги, у тебя есть свой KPI, и тебя постоянно оценивают: как ты эту бумажку берешь, как несешь, как ровно ты ее положил. Тебе нельзя выходить за рамки своих задач. При этом скреплять листы степлером — это уже работа другого человека. В Яндексе нас мало, а проектов очень много, поэтому у тебя невероятная (по американским меркам) свобода как у технаря.

Есть еще китайцы, Baidu. Но там другая история. Как говорили про Baidu одни мои западные товарищи, которые с ними работали: «Мы пришли, и нам дали в помощь небольшой отдел из 500 человек». То есть они берут числом.

JS: Теория

Здесь обсуждались темы декларирования и лексического окружения функции, написании конструкторов на функциях, разбирались что будет, если функцию конструктор вызвать без ключевого слова и избежать побочного эффекта в таких ситуациях. После вспомнили о IIFE, как и для чего это использовалось, поговорили о модели наследования в JS, доступности и переопределении свойств, разобрались с методами у класса , которые помогают работать со свойствами. И в конце немного затронули тему о средствах выполнения http-запросов, передачи и хранении данных.

При подготовке я не ожидал, что вся секция будет построена вокруг ECMAScript 5, но благодаря знаниям полученным из книжки “с носорогом”, кажется, не ударил лицом в грязь.

Дорогой дядюшка Девид, спасибо!

Скайп-интервью

Перенесемся на пару недель до собеседования в офисе Яндекса. По своей сути скайп-интервью, это очное интервью на минималках: за час времени кандидату предлагается решить пару логических задач в блокноте и задача на верстку:

// Обращение к свойству объекта/*const o = {  a: {    b: {},    c: 42  },  z: null};(o, 'a.c') => 42(o, 'a.d') => undefined(o, 'z') => null*/// Сжатие строки// ('AAABbbbBcCCC') => 'A3Bb3BcC3'

Задание на верстку было сформулировано примерно следующим образом:

О сроках

Весь процесс прохождения интервью занял 3 недели, если за отправную точку брать дату получения первого письма от HR-менеджера, а за дату окончания — день получения письма с результатом о прохождении очного интервью. Для полноты картины можно накинуть неделю на период анализа и реакции на ваше резюме и еще неделю-две на финальное интервью с командой и формальности.

В итоге

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

К сожалению, точно мне неизвестно, было ли принято решение об отказе лишь по одной секции. Но если так, то странно видеть, что при наличии трех секций одинаковой сложности, одна из них имеет больший вес только из-за своего названия.

Спасибо, у меня всё. А вы делитесь с друзьями и коллегами, комментируйте, ну или лайкните.

TL;DR

  1. Если есть, возьмите свой ноутбук на очное собеседование;
  2. Согласуйте очередность секций на очном собеседовании;
  3. Решите с десяток-другой задач с сайта http://codewars.com в блокноте;
  4. Освежите теорию по книге, например, “с носорогом”.

Как мы собеседуем разработчиков

Собеседование любого разработчика состоит из нескольких этапов:

  • предварительная секция с рекрутером;
  • техническое скайп-интервью;
  • несколько очных секций;
  • финальные интервью с нанимающими менеджерами.

На предварительной секции рекрутер знакомится с кандидатом, узнаёт его интересы и мотивы для того, чтобы понять, на какие позиции имеет смысл его рассматривать. Техническое скайп-интервью предназначено для предварительной оценки навыков кандидата и отсеивает тех, кто со всей определённостью не справится с очными секциями.

Очные секции — основной этап. Именно очные секции дают ответ на вопрос о том, что умеет кандидат. Алгоритмическая секция — одна из очных технических секций. Помимо алгоритмических, бывают и другие очные испытания: скажем, кандидаты в старшие разработчики обязательно проходят секцию по архитектуре, а будущие руководители ещё и отвечают на вопросы по управлению командами и проектами. Вообще, если у кандидата есть какая-то сильная сторона в специфической области (машинном обучении, низкоуровневой оптимизации, разработке высоконагруженных систем, мобильной разработке или любой другой) — мы обязательно организуем секцию с профильным специалистом.

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

C. Удаление дубликатов

Начнём с простой реализации. Определим функцию initial, которая считывает число, печатает его и возвращает завернутым в монаду IO. Также определим функцию deleteDoubles :: Int -> Int -> IO(), которая считывает число и печатает в его только в случае, если оно не равно второму аргументу (будем передавать туда число прочитанное на предыдущем шаге). После этого функция рекурсивно вызывает сама себя и таким образом переходит к следующему числу во входном потоке. Базой рекурсии является количество чисел, которое предстоит прочитать, будем передавать его первым аргументом.

Отправляем решение, оно проходит все тесты, и, казалось бы, можно двигаться к следующей задаче, но на мой взгляд рекурсивный вызов функции, работающей в монаде IO, является скорее запутанным, чем лаконичным. Попробуем его улучшить.

Заметим, что, вообще говоря, можно сначала прочитать весь список чисел (воспользуемся уже знакомым по решению второй задачи комбинатором replicateM), затем передать его в чистую функцию, которая отфильтрует все повторения, и в итоге напечатать результат.

Отправляю решение, и первое разочарование – программа не проходит 193 тест из-за превышения лимита используемой памяти. Главная ошибка – чтение всего списка в память целиком. Попытаемся этого избежать и реализуем некий гибрид первой и второй версии.

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

Функция, которая печатает или не печатает результат в зависимости от своих аргументов, после чего возвращает свой второй аргумент, завёрнутый в монаду IO, довольно проста, назовём её step:

С печатью или не печатью в зависимости от переданных значений мы разобрались, но как организовать чтение? Для этого воспользуемся функцией монадической свертки foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b, которую применим к списку функций чтения.
По типу функции foldM заметим, что на каждом шаге «распаковка» результата прошлого применения функции происходит под капотом самой foldM. Таким образом, на каждом шаге нам необходимо только запустить монадическое вычисление текущего элемента списка (по сути – прочитать следующее число) с помощью оператора bind (>>=) и вместе с предыдущим числом передать в step. В итоге получаем следующую программу

Описание

Яндекс.Трекер — это облачный сервис для организации работы в компании: распределения ресурсов и контроля выполнения задач. Практически любой процесс — от разработки приложения до согласования документов — в Трекере можно сделать прозрачным и удобным для всех участников.

Возможности сервиса

Задачи. Для каждой задачи в Трекере заводится своя страница — с описанием, ответственными, сроками выполнения, ссылками на связанные задачи и другой информацией. Там же удобно запрашивать необходимые данные, обсуждать детали и согласовывать результаты. Все заинтересованные получают уведомления о новых комментариях, а договоренности фиксируются на странице задачи и не теряются в почте и мессенджерах.

Очереди. Задачи разных отделов и команд группируются по отдельным очередям. Набор параметров задачи в каждой из них может быть своим. Например, команде, работающей по методологии Agile, нужны поля с информацией о спринтах и итерациях, а рекрутерам — с данными о профессии и навыках соискателя. В Трекере есть несколько стандартных типов очередей и возможность настраивать очереди под конкретные процессы.

Фильтры. Чтобы ориентироваться в задачах было удобнее, можно настроить фильтры для их отображения и группировки в списке — например, «все задачи с высоким приоритетом, отсортированные по дедлайну». Для создания фильтров по сложным сочетаниям параметров можно использовать язык запросов.

Доски Agile. Компании, использующие методологию Agile, смогут работать в Трекере в привычном режиме — он поддерживает все необходимые функции. Отдельные инструменты Agile, такие как визуальные доски задач, в Трекере можно использовать и в отрыве от методологии, не разбираясь в том, что такое story points и как они сгорают.

Учёт времени и трудозатрат. В Трекере есть возможность вести учёт времени, потраченного на задачу. Особенно полезна эта функция может быть при работе с подрядчиками. Кроме того, с её помощью можно измерять, сколько времени обычно требуется на задачу определённого типа, и использовать эти знания при планировании и распределении ресурсов.

Шаблоны задач и комментариев. В Трекере можно создать шаблоны с описанием типовых задач. Это избавляет от рутинного составления ТЗ, а если задачу ставит новый сотрудник — помогает не забыть о деталях. Шаблоны пригодятся и в комментариях — например, для ответов на часто возникающие вопросы, предоставления инструкций или перечней необходимых документов.

Живые задачи. Если на странице задачи, открытой в браузере, произойдут какие-то изменения — например, появится новый комментарий или изменится статус готовности — вы сразу об этом узнаете

На корешке вкладки появится красная метка, а на самой странице — уведомление об изменениях.

Напоминания и призывы. Чтобы точно не упустить что-то важное за потоком других дел, в Трекере можно ставить самому себе напоминания о задачах — в заданный день и час вы получите письмо
Чтобы обратить внимание другого сотрудника на задачу, в которой он срочно нужен, его можно призвать в комментарии — он получит уведомление на почту с пометкой о срочности.

Порядок в работе с заявками. В Яндекс.Трекере можно организовать работу с заявками от клиентов и сотрудников — так, чтобы обращения не терялись и не оставались без ответа
Направьте в Трекер все заявки, которые вам присылают на почту или оставляют через формы, — и процесс обработки будет удобным и прозрачным для всех заинтересованных сотрудников.

Перенос задач в Трекер. Если вы использовали другой сервис управления проектами или отслеживания задач, можно перенести ваши данные в Трекер, чтобы сохранить историю и продолжить работу с привычными задачами

Для переноса данных можно воспользоваться API Яндекс.Трекера.

Мобильное приложение. В мобильном приложении Трекера можно создавать новые задачи, управлять людьми и статусами, отвечать на комментарии. С ним сложнее пропускать уведомления об изменениях в задачах — вы будете получать уведомления прямо на телефон. Также в нём можно использовать готовые и добавлять новые фильтры.

Вторая секция

Во второй секции я общалась с девушкой, собеседовавшей меня по скайпу. Она занимается внутренним проектом Яндекса, посвященным рекрутингу и эта секция была посвящена верстке. Интервьюер знала, что в верстке я не сильна еще с онлайн-беседы, но все же мы поговорили о всяких разных интересных вещах.

  1. Общее понятие о флексбоксе, гридах и других методах построения layout.
  2. Верстка под мобильные устройства, понятие mobile first, как можно работать с картинками на мобильных устройствах, что делать с retina дисплеями.
  3. Специфика верстки под мобильные устройства, особенности events, особенности :hover().
  4. Тэг picture и атрибут srcSet.
  5. Специфичность селекторов с простенькой задачкой:
<div class="one two">div {background-color: 'red';}.one.two {background-color: 'green';}.one {background-color: 'blue';}div.one{background-color: 'yellow';}

6. Разные способы задать цвет в верстке на примере красного цвета.

7. Поддержка старых браузеров, понятия graceful degradation и progressive enhancement.

8. Классическая задача на центрирование дива по вертикали и горизонтали, с требованием привести максимальное количество способов центрирования:

<body>  <div class="myDiv"></div></body>.myClass {  background-color: red;  width: 100px;  height: 100px;}

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

<div>Очень-очень длинный текст<button>Надпись</button></div>

Между второй и третьей секциями рекрутер прорекламировала мне Яндекс со всех сторон, рассказала про все бонусы и про все, про что положено говорить рекрутеру. Потом мы с ней зашли в близлежащий Старбакс, перекусили, взбодрились кофе и вернулись продолжать собеседование.

DevOps

Есть модное слово, которого я стараюсь всячески избегать, — DevOps. Это принцип синергии разработчика, админа и даже безопасника. Сперва поясню, как работает классическая схема.

Разработчик написал и запустил сервис, через какое-то время сервис упал. Разработчик говорит администратору: «Ты не умеешь админить! Я пишу отличный код, а ты не умеешь его эксплуатировать!» Администратор спорит: «Нет, я нормальный админ. Это ты написал программу, которая течет и падает, ты не умеешь писать код!» Потом этот сервис ломают, и данные утекают. Админ и разработчик приходят к безопаснику и вместе начинают орать уже на него. Теперь это он виноват, потому что не умеет нормально проверять код на безопасность.

Так вот, культура DevOps отучает перекладывать вину на других. Пока для большинства это лишь модное слово, но мы в последние годы перестроились в этом направлении. Все мы в одной лодке. То есть ты написал код, ты же его и поддерживаешь. Есть инструменты безопасности, которые для тебя сделаны. Они интегрированы в твой процесс сборки и тестирования.

Заключение

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

Оказался ли функциональный подход удобен для решения подобного рода задач? Честно говоря, у меня осталось двоякое впечатление. С одной стороны, решения большинства задач оказывались весьма лаконичными, и не последнюю роль в этом сыграли выразительные средства самого Haskell, а также его богатая стандартная библиотека. С другой, нельзя не признать, что в большинстве случаев управление потребляемыми ресурсами может представлять собой определенную проблему, что не позволит решить задачу в заданных ограничения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector