Рубрика «ruvds_переводы»

Анализ задачи с собеседования в Google: конь и телефонные кнопки - 1


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

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

  • Её легко сформулировать и понять.
  • У неё есть множество решений, каждое из которых требует разной степени знаний алгоритмов и структур данных. Кроме того, здесь важны логические рассуждения.
  • Каждое решение можно реализовать в относительно малом объёме кода, поэтому она идеальна для ограниченных по времени собеседований.

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

Почему я предпочитаю исключения, а не значения ошибок - 1


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

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

Давайте рассмотрим пример, в котором применено защищённое от ошибок целочисленное деление:

int safeDiv(int a, int b) {
   if (b == 0)
      throw Div0(); // Исключения передаются особым образом
   return a / b; // Теперь-то всё абсолютно безопасно, ведь так?
}

Новые языки программирования склонны применять сообщения об ошибках в функциональном стиле и кодировать ошибки в возвращаемый тип. Например, Go кодирует ошибку в возвращаемый тип при помощи кортежа (res, err), а Rust возвращает Result<T, E> — тип-сумму результата и ошибки.
Читать полностью »

Советы по программированию, которые бы я дал себе 15 лет назад - 1

У меня наконец-то появилось ощущение, что я хороший программист, поэтому было бы неплохо записать советы вида «как бы я смог добиться этого быстрее?». Не буду утверждать, что все эти советы отлично подойдут всем, но для меня они были бы хорошими.

▍ Если ты (или твоя команда) постоянно стреляешь себе в ногу, то почини ружьё

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

Когда я занимался разработкой для iOS, то использовал CoreData и подписывался на изменения нескольких view. Обратный вызов подписки поступал в тот же поток, из которого было запущено изменение. Иногда это был основной поток, а иногда — фоновый. В разработке для iOS важно то, что вносить изменения в UI можно только в основном потоке, иначе приложение вылетит. Поэтому подписка могла работать нормально, но потом ломалась, когда кто-то запускал изменение из фонового потока или вы позже добавляли обновление UI.

Все без раздумий воспринимали это как что-то само собой разумеющееся, и об этом часто говорили в ревью для новичков в команде. Время от времени кто-нибудь ошибался, и мы добавляли DispatchQueue.main.async, когда видели отчёт о сбое.

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

Как я портировал свой игровой движок с JavaScript на C - 1

high_impact

tl;dr: high_impact — это маленький игровой движок для 2D-игр жанра «экшн». Он написан на C, компилируется для Windows, Mac и Linux, а также для WASM в вебе. Он был написан «по мотивам» моего игрового движка Impact на JavaScript, разработанный в 2010 году. Название high_impact — отсылка к тем временам, когда C считался языком высокого уровня.

Движок имеет лицензию MIT, исходники выложены на Github: github.com/phoboslab/high_impact

Видео из моего твита за 5 июля, демонстрирующее геймплей Biolab Disaster
Читать полностью »

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

▍ Оптимизация роботов (автор: Rseding)

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

Factorio: оптимизации 2.0 - 1

Типичная фабрика с кучей дронстанций (Roboport)

Дронстанции никогда не были «медленными», но они всегда присутствуют на карте, и у игроков есть мотивация строить их в больших количествах; к тому же, их будет ещё больше в грядущем Space Age, где нужно будет многое делать удалённо. Сохранение, полученное после последней сессии плейтестинга, снова показало, что они отнимают небольшое, но ненулевое количество времени, поэтому я снова задумался о них.Читать полностью »

Находим случайный seed, решающий задачу с LeetCode - 1


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

Одним из ежедневных челленджей LeetCode была такая задача (я немного упростил её для понятности):

Есть список из $k$ уникальных строк битов, каждая из которых имеет длину $k$. Сгенерировать новую строку длиной $k$, отсутствующую в этом списке.

Например, если у нас есть список "010", "110", "111", то возможным решением будет "001". Задача с LeetCode имеет большой набор тестов — 183 тестовых сценариев с $1≤k≤16$, а точную формулировку задачи можно найти здесь.

Я решил её, подобрав такое случайное порождающее значение (seed), что случайно генерируемые строки битов проходили бы все тестовые сценарии. Вот код решения:

class Solution:
    def findDifferentBinaryString(self, nums: List[str]) -> str:
        random.seed((69299878 + sum(ord(c)*(i*j+111) for (i, n) in enumerate(nums) for (j, c) in enumerate(n))) % 999999999)
        return ''.join(random.choice('01') for _ in nums)

Можете попробовать это решение самостоятельно (оно должно работать, если LeetCode не обновил свой набор тестов. Если это произошло, сообщите мне об этом).

Ниже я расскажу, как это сделал.Читать полностью »

Прошлой осенью я участвовал в недельном мероприятии по программированию Wheel Reinvention Jam. Смысл этого джема заключается в том, чтобы взглянуть по-новому на уже существующие программные системы. Я написал для него 3D-редактор под названием ShapeUp. Пост будет понятнее, если вы сначала посмотрите видео-демо ShapeUp. Можно попробовать ShapeUp в браузере.

Вот, как он выглядит:

Пишем за неделю 3D-редактор на C - 1

Майк Вазовски!

3D-редактор

Я ненавижу тормознутость компилятора Typescript (поверьте, это относится к теме статьи). Джем показался мне подходящей возможностью реализовать более быстрое подмножество Typescript, обгоняющее по скорости tsc. Мне показалось, что проект можно реализовать, если начать с парсера Typescript esbuild or Bun. Но потом ко мне пришло понимание, что успешный результат будет выглядеть как команда терминала, выполняющая работу быстрее другой. Не особо впечатляюще в качестве демо. Мне хотелось создать крутое демо, поэтому я выбрал 3D.
Читать полностью »

Если вы программист или хотя бы немного связаны с программированием1, то без сомнения сталкивались с таблицей ASCII.

Таблица ASCII полезна. Но знали ли вы, что она ещё красива и изящна?

Красота и изящество таблицы ASCII - 1

Сегодня даже не близкие к программированию люди могут знать об ASCII благодаря книгам и фильмам наподобие «Марсианина»2

ASCII по-прежнему с нами; даже если вы передаёте современный Unicode3, то должны знать, что самый популярный формат кодировки UTF-8 специально спроектирован как обратно совместимый с ASCII! Декодировав эту статью как ASCII, вы в целом поймёте её смысл… если закроете глаза на мусорные символы в конце предложений (прим. ред.: имеет смысл только для оригинальной статьи на английском).Читать полностью »

Побеждаем компилятор в скорости при помощи ассемблера - 1


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

Тем не менее, иногда до нас доносятся слухи.

Написанные в древних томах, подслушанные в тайных покоях, начертанные на стенах разрушенных храмов, упоминаемые в загадочных текстах, они рисуют чёткую картину:

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

Читать полностью »

Реверс-инжиниринг умных часов - 1


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

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


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js