<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Красивый хак</title>
    <description>Статьи  с описанием хитрых приемов разработки, которые помогут вам сэкономить время и эффективно решить возникшую проблему.</description>
    <link>https://tproger.ru/tag/good-hack</link>
    <atom:link href="https://tproger.ru/tag/good-hack/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Mon, 05 Oct 2026 14:43:53 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Красивый хак</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Локализация через Enum, неожиданный Дзен, быстрее только телепатия</title>
      <link>https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat</link>
      <comments>https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Самир Гёзалов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat</guid>
      <description><![CDATA[<p>Надоело плодить JSON/ARB файлы при локализации Flutter-приложения? Автор делился личным опытом и показал, как элегантно настроить локализацию через Enum без внешних зависимостей, генераторов кода и боли в рантайме.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat">Локализация через Enum, неожиданный Дзен, быстрее только телепатия</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Массивы и строки]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Flutter]]></category>
      <category><![CDATA[Dart]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 04 Jun 2026 04:45:17 GMT</pubDate>
      <content:encoded><![CDATA[<p>Решил давеча добавить локализацию в свое приложение на Flutter. Задачка-то простая: пара кнопок, пару десятков переменных. Казалось бы, делов на пять минут. Но Flutter «из коробки» сразу попытался всучить мне какую-то дичь в виде ARB и JSON файлов. Хмм, из прошлого с такими реализациями лишь печаль, так что…</p><h2>Попытка №1. Путь в лоб: Классы и интерфейсы</h2><p>Самый очевидный способ - создать родительский класс с переменными, а языки сделать его наследниками. Но это просто… фиаско. Даже если не писать from/toJson, процесс выглядит так:</p><ol><li>Объявил переменную в родителе.</li><li>Прописал её в конструкторе.</li><li>Повторил то же самое для всех дочерних классов (всех языков).</li></ol><p>Если бы я работал на аутсорсе в Индии и мне платили за количество строк кода - это был бы идеальный вариант. Но я хотел, чтобы одной строки при объявлении было достаточно.</p><h2>Попытка №2. Стандарт (ARB/JSON)</h2><p>Я поплевался, но решил попробовать - «стандарт» всё-таки. Мало ли, может чего поменялось за годы. Вроде всё завелось, но сам процесс… это боль. Бегать по разным файлам, чтобы добавить одну строчку - так себе удовольствие.</p><p>Почему я от него окончательно отказался? Когда данных становится реально много (десятки языков, тысячи строк), ты попадаешь в ловушку: тебе нужно эту махину либо целиком держать в памяти, либо постоянно подгружать и парсить. Ради смены одного слова на кнопке заставлять девайс ворочать тяжелые JSON-ы в рантайме - так себе затея для производительности.</p><h2>Попытка №3. Таблицы и костыли</h2><p>Подумал: «Окей, почему бы не подтянуть старый добрый CSV или вообще закинуть всё в табличку?». И тут официальный пакет локализации сказал: «Извини, мужик, тут наши полномочия всё».</p><p>Ну, я тоже не пальцем деланный. Решил припахать нейросеть, чтобы она написала мне собственный генератор. Флоу получился такой:</p><ol><li>Добавляю строку в таблицу.</li><li>Запускаю генератор.</li><li>Он лепит «родительский» файл.</li><li>После Freezed генерит toJson, fromJson…</li></ol><p>Короче, весело не было. Мало того, я понимал: если языков станет много, мне придется добавлять их все разом и единовременно, иначе в рантайме всё начнет плеваться ошибками. Плюс та же проблема с памятью: таблица - это структура, которую надо парсить и хранить.</p><h2>Красный флаг для программиста</h2><p>Но главная проблема даже не в этом. Необходимость запускать генератор после добавления каждой переменной - это для любого программиста красный флаг.</p><p>Что происходит на практике? Когда ты пишешь код и тебе нужно добавить одну несчастную строку, тебе лень (читать: нехочется выходить из потока творения) запускать весь этот цикл с генерацией. Ты просто её хардкодишь в надежде «потом скопом всё добавлю одним махом». А «потом» наступает тогда, когда уже весь проект завален хардкодом, и вычищать его - то еще удовольствие. Даже нейросетки с такими запросами помогают не с первого раза, и с сомнительной эффективностью.</p><p>Нутром чуял - флоу неправильный. В итоге я пришел к тому, что называю идеальной локализацией.</p><h2>Эволюция лени: почему Enum победил интерфейсы</h2><p>Я начал мучить нейросеть разными вариантами реализации. Для меня в первую очередь был важен флоу работы: мне было тупо лень писать больше одной строки кода, чтобы добавить переменную.</p><p>Моя философия проста: строку захардкодить - моментально. Добавление даже одной строки в другом файле требует доп. действий. НО, если действий минимум, то кодер поймет, что выигрыш во времени сейчас мизерный против больших потерь в будущем, и исправно добавит строку в правильное место. Этого не произойдет, если для добавления строки нужно «отчитаться» в десяти местах.</p><h2>Попытка №4. Рекорды (Records)</h2><p>Присматривался к рекордам. С ними удобно: не нужно писать конструкторы. Но есть подвох: как только ты добавил переменную в один язык, компилятор тут же сходит с ума и требует добавить её во все остальные прямо сейчас. Никакой гибкости и возможности оставить «на потом».</p><h2>Идеальный костыль: Enum</h2><p>В итоге я пришел к самому, казалось бы, «неправильному» способу, который оказался идеальным. Enum. Само название намекает на перечисления и цифры, но оказалось, что хранить в нем буквы и целые фразы - это лучший путь для локализации.</p><p>Знаете, мне моё решение так понравилось, что я пошел к нейросетям и проверил его со всех сторон. Все модели  остались в полном восторге. Под это дело я даже подготовил монументальную «нейро-статью» на полтора часа внимательного чтения, со всеми графиками, бенчмарками и анализом производительности.</p><p>Но потом я заглянул в правила Хабра, прислушался к голосу разума и понял: никто не хочет читать полтора часа сухой статистики. Лучше я просто расскажу вам свою историю «от первого лица», как я докатился до такой жизни. Ну, а если вы совсем уж фанаты цифр - просто скормите этот текст любой нейронке, она вам перескажет всё в лучших академических тонах с графиками на любой вкус.</p><p>А здесь мы будем говорить по делу.</p><p>Ниже я выкатываю сам код. Код тут не для зубрежки, а лишь чтобы указать направление / идею. Самая большая прелесть этой системы в том, что она оставляет гигантское пространство для любого типа реализации. Это архитектурный каркас, который чертовски сложно сломать. Главное — уловить принцип.</p><h2>Реализация</h2><p>Принцип разделения:</p><ul><li>enum Strings → типизированный контракт (что существует).</li><li>translator → источник данных (откуда берётся текст).</li></ul><p>Структура файлов - минимальная. Никаких внешних зависимостей:</p><h2>Ядро - strings.dart</h2><p>Весь контракт локализации в одном enum. Два режима - хардкод switch и серверный кеш - за одним и тем же</p><p>. Даже сообщения об ошибках локализации — сами локализованы:</p><h2>Список языков - languages_enum.dart</h2><p>Каждый язык - самодостаточная единица: знает свой код, название, направление текста и как себя загрузить:</p><p>Хотите грузить с сервера? Одна строка + loader. И</p><p>- тоже одна строка, потому что</p><p>уже является registry:</p><h2>Переводчик - i18n/russian.dart</h2><p>Как это выглядит в жизни (и почему я перестал хардкодить) Я намеренно не привожу здесь код оберток виджетов или конкретных стейт-менеджеров. Всё это - чистая «вкусовщина». Для работы системы нужен лишь элементарный вещатель событий (Notifier), повешенный на метод смены языка.</p><p>Но главное - это мой ежедневный флоу. Сейчас, чтобы добавить строку в UI, я просто вызываю нужный мне ключ: Strings.someKey(). Без контекста, везде.</p><p>А если ключа еще нет? Я тупо иду в Strings и добавляю одну строчку в Enum. Всё.</p><p>Благодаря дефолтному конструктору, приложению абсолютно плевать, что у меня там еще 100 языков не переведены. Оно компилируется и работает здесь и сейчас. А дальше в дело вступают гит-хуки: при комите нейросетка сама подхватывает изменения и заполняет недостающие поля в переводчиках.</p><p>Знаете, какое самое странное чувство? Мне сейчас реально проще и быстрее завести переменную в локализации, чем хардкодить строку в коде. Кажется, это и есть признак здоровой архитектуры - когда делать «правильно» становится физически удобнее, чем делать «быстро» и криво.</p><p>Собственно если в кратце это все о чем я хотел рассказать. Если тема зайдет или кто-то сам не сможет допереть, как прикрутить это к своей архитектуре - пишите в комментариях, разберемся.</p><p>Надеюсь, мой опыт сэкономит вам пару литров нервных клеток. Всех благ и чистого кода без «магических строк»!</p>]]></content:encoded>
    </item>
    <item>
      <title>Разработчик создал эмулятор процессора x86 на чистом CSS — без единой строчки JavaScript</title>
      <link>https://tproger.ru/news/emulyator-processora-x86-na-chistom-css--ni-strochki-javascript</link>
      <comments>https://tproger.ru/news/emulyator-processora-x86-na-chistom-css--ni-strochki-javascript?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Картофельный Повелитель]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/emulyator-processora-x86-na-chistom-css--ni-strochki-javascript</guid>
      <description><![CDATA[<p>Lyra Rebane создал полноценный эмулятор процессора x86 на чистом CSS — без JavaScript и WebAssembly. Проект использует экспериментальные функции CSS: if(), style queries и @function.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/emulyator-processora-x86-na-chistom-css--ni-strochki-javascript">Разработчик создал эмулятор процессора x86 на чистом CSS — без единой строчки JavaScript</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[CSS]]></category>
      <category><![CDATA[Браузеры]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 06 Mar 2026 07:44:26 GMT</pubDate>
      <content:encoded><![CDATA[<p>Lyra Rebane создал(а) <a href="https://lyra.horse/x86css/">x86CSS</a> — полноценный эмулятор процессора архитектуры x86 на чистом CSS. Никакого JavaScript или WebAssembly — все вычисления происходят исключительно силами браузерного движка стилей.</p><h2>Как это работает</h2><p>Эмулятор исполняет реальный машинный код для процессоров <a href="https://en.wikipedia.org/wiki/Intel_8086">Intel 8086</a>. Тактовый генератор построен на CSS-анимациях в сочетании со style container queries, поэтому система работает автономно и не требует от пользователя никакого взаимодействия — программа крутится сама.</p><p>Логика реализована благодаря новым возможностям CSS, которые пока доступны только в экспериментальном виде:</p><ul><li>условные операторы <b>if()</b></li><li><b>style queries</b> (стилевые запросы контейнера)</li><li>кастомные <b>@function</b></li></ul><p>На странице проекта есть скрипт-тег, но он лишь ускоряет работу тактового генератора. Если отключить JavaScript, эмулятор продолжит работать — просто чуть медленнее и менее стабильно.</p><h2>Запуск собственных программ</h2><p>В эмуляторе можно запускать собственные программы. Достаточно написать код на C и скомпилировать его через <a href="https://gitlab.com/tkchia/build-ia16">gcc-ia16</a> с помощью скрипта из <a href="https://github.com/rebane2001/x86css">репозитория</a> автора. На выходе — готовый HTML-файл со стилями, внутри которого исполняется ваш бинарник.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-03-06/46d28142-b0a2-47e0-85cf-923ecfdd4f03.webp" alt="Репозиторий x86CSS на GitHub" /><figcaption>Репозиторий проекта на GitHub — 726 звёзд, лицензия GPL-3.0</figcaption></figure><p>По умолчанию эмулятору доступно 1,5 КБ памяти, но этот лимит можно увеличить в конфигурации. Программа загружается по адресу 0x100, предусмотрены специальные адреса ввода-вывода для взаимодействия с «железом» — экранным выводом и клавиатурой.</p><h2>Ограничения и совместимость</h2><p>Практического применения у проекта нет — производительность крайне низкая. Зато это отличная демонстрация того, что современный CSS действительно стал тьюринг-полным.</p><p>Из-за использования экспериментальных CSS-функций запустить демку пока можно <b>только в браузерах на базе Chromium</b> (Chrome, Edge, Opera и т.д.). Firefox и Safari пока не поддерживают нужные спецификации, хотя все используемые фичи входят в официальный стандарт CSS.</p><p>Отдельно автор подчёркивает: проект создан полностью вручную, <b>без использования ИИ</b>. CSS написан в Sublime Text, а для генерации повторяющихся частей кода использовался Python-скрипт.</p><p>Попробовать эмулятор можно на <a href="https://lyra.horse/x86css/">сайте проекта</a>, исходный код доступен на <a href="https://github.com/rebane2001/x86css">GitHub</a> под лицензией GPL-3.0.</p>]]></content:encoded>
    </item>
    <item>
      <title>Почему технологии 80-х тормозят корпоративные коммуникации и что с этим делать</title>
      <link>https://tproger.ru/articles/pochemu-tehnologii-80-h-tormozyat-korporativnye-kommunikacii-i-chto-s-etim-delat</link>
      <comments>https://tproger.ru/articles/pochemu-tehnologii-80-h-tormozyat-korporativnye-kommunikacii-i-chto-s-etim-delat?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Игорь Кальметов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/pochemu-tehnologii-80-h-tormozyat-korporativnye-kommunikacii-i-chto-s-etim-delat</guid>
      <description><![CDATA[<p>Почему корпоративная почта до сих пор работает на стандартах прошлого века? И можно ли это изменить без отказа от привычного формата? Разбираемся на примере стандартных протоколов и рассказываем, как мы в «МБК Лаб» подошли к решению этой проблемы.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/pochemu-tehnologii-80-h-tormozyat-korporativnye-kommunikacii-i-chto-s-etim-delat">Почему технологии 80-х тормозят корпоративные коммуникации и что с этим делать</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Сетевые протоколы]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 26 Jul 2025 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Электронная почта остаётся одновременно незаменимым и устаревшим способом коммуникации. Это всё ещё основной путь для официальной деловой переписки, без которого не обходится ни одна крупная организация. Но в то же время — это технология, архитектура которой практически не изменилась с 1980-х годов.</p><h2>Что такое почтовые протоколы и почему они определяют всё</h2><p>Почтовый протокол — это набор правил, по которым устройства и программы обмениваются email-сообщениями. Он определяет, как письмо отправляется, передается, хранится и извлекается. Именно эти протоколы лежат в основе любой почтовой инфраструктуры — от личных ящиков до корпоративных систем.</p><p>Существуют как открытые, так и закрытые (проприетарные) протоколы. Открытые стандарты доступны всему рынку, закрытые принадлежат отдельным компаниям (например, Microsoft). Большинство современных почтовых систем до сих пор работает на открытых протоколах, разработанных в XX веке:</p><ul><li>SMTP (1982 год, RFC 821) — используется для отправки писем с почтового клиента на сервер и между серверами, но не предназначен для получения писем пользователем.</li><li>IMAP (первая версия — 1986 год, RFC 1064; текущая версия IMAP4 — RFC 3501, 2003) — используется для доступа к письмам на сервере без их загрузки, с возможностью синхронизации между устройствами. Например, что прочитано на одном устройстве, будет отмечено прочитанным и на другом.</li><li>WebDAV / CalDAV / CardDAV (с конца 1990-х) — для управления файлами на сервере, работы с календарями, адресными книгами и контактами.</li></ul><p>Из проприетарных — MAPI от Microsoft (в начале 1990-х годов) обеспечивает тесную интеграцию почты, календарей, контактов и задач между клиентом (Outlook) и сервером (Microsoft Exchange).</p><p>Эти протоколы универсальны и поддерживаются большинством почтовых клиентов. Но их возраст — главная проблема.</p><h2>Технологии 80-х против задач 2020-х</h2><p>Стандартные почтовые протоколы создавались в эпоху, когда интернет был медленным, письма — короткими, а безопасность и мобильность не были приоритетами. С тех пор многое изменилось, а они — почти нет. Это делает инфраструктуру электронной почты неготовой к требованиям современного бизнеса. Вот с чем сегодня сталкиваются ИТ-отделы и пользователи:</p><ul><li>Ограничения на размер сообщений. SMTP технически не предназначен для передачи больших файлов: вложения кодируются и увеличиваются в объёме, а большинство серверов ограничивают размер письма 25 МБ. Видео, презентации и таблицы нередко «не проходят».</li><li>Медленная доставка. В классических протоколах нет push-механизма — клиенты запрашивают почту вручную или по таймеру. На мобильных устройствах это особенно заметно — письма приходят с задержкой.</li><li>Нет встроенного шифрования. SMTP и IMAP изначально не защищены. Шифрование реализуется через внешние надстройки (например, STARTTLS), и далеко не все системы его поддерживают по умолчанию.</li><li>Разрозненность функций. Почта, календарь и контакты работают по разным протоколам: SMTP, IMAP, CalDAV, CardDAV. Это требует сложной настройки и дает нестабильный результат — особенно в гибридных или распределенных средах.</li><li>Нет централизованного управления. В открытых протоколах нельзя массово настраивать клиентские приложения, удалять учетные записи с устройств или управлять профилями пользователей. Это затрудняет администрирование и снижает безопасность.</li><li>Уязвимость к атакам. IMAP и SMTP в открытых конфигурациях — популярная мишень. Почта давно стала основным каналом проникновения. По данным BI.ZONE CESP, в 2024 году число вредоносных вложений в корпоративной почте выросло на 250%, а фишинговых ссылок — на 25%.</li></ul><p>Такие изъяны особенно критичны для корпоративных почтовых систем, где требуется высокая функциональность, масштабируемость, надёжность и защита данных.</p><h2>Открытый протокол 2TMTP</h2><p>Чтобы почта соответствовала современным требованиям, нужен принципиально новый протокол — не «костыль» над старым, а полноценная замена. Мы в «МБК Лаб» разрабатываем такой стандарт — 2TMTP.</p><p>Это открытый протокол, который можно свободно использовать и встраивать — и на стороне сервера, и на стороне клиента. Его архитектура построена с нуля, с учетом того, как работают современные компании, в том числе — крупные и распределенные.</p><p><b>Что умеет 2TMTP:</b></p><ul><li>Передача любых типов данных без ограничений по объему: письма, файлы, календари, задачи, контакты.</li><li>Встроенное сквозное шифрование — по умолчанию, без внешних решений.</li><li>Push-доставка и подтверждение прочтения — как в мессенджерах.</li><li>Автонастройка клиента и автоудаление профиля — удобно для MDM и гостевого доступа.</li><li>Централизованное управление профилями: настройка прав, политик, внешнего вида клиента с серверной стороны.</li><li>Работа между серверами — не только клиент-сервер, как у SMTP, но и сервер-сервер с полной синхронизацией.</li><li>Поддержка fallback-режимов. Если одно из устройств не поддерживает 2TMTP, можно откатиться на SMTP или IMAP. Протокол встроен в стандарт ESMTP CAPABILITY и активируется при обоюдной поддержке.</li></ul><h2>Чем 2TMTP отличается от MAPI</h2><p>MAPI — это ближайший аналог 2TMTP по функциональности, но он полностью закрыт. Протокол используется только в экосистеме Microsoft (Outlook + Exchange), и сторонние разработчики не могут интегрировать его в свои решения. Кроме того, в отличие от MAPI, который ограничен клиент-серверным взаимодействием, 2TMTP также поддерживает полноценное межсерверное общение. В результате 2TMTP не имеет лимита на размер передаваемого сообщения, в то время как почта Microsoft ограничена 25 МБ, поскольку для передачи данных между серверами переходит на стандартный SMTP.</p><p>2TMTP — открытый. Любая российская или зарубежная компания сможет встроить его в свою почтовую систему или клиент и получить техническую поддержку. Это делает его универсальной платформой для почтовой инфраструктуры в России, странах ЕАЭС, БРИКС.</p><h3>Когда будет доступен новый протокол</h3><p>На данный момент разработка стандарта 2TMTP полностью завершена. Тем не менее, для его официального внедрения потребуется время на юридические процедуры и регистрацию. Мы ожидаем завершить эти этапы до конца 2025 года — в начале 2026 года протокол станет доступен для широкого использования.</p><p>Каждый разработчик почтового сервиса сможет интегрировать 2TMTP и получить техническую поддержку от нашей команды.</p><h3>А что со старым добрым SMTP</h3><p>SMTP работает на миллиардах устройств в мире. Совершенно очевидно, что ещё много десятков лет, он сохранит свою работоспособность. Естественно, расширяя функциональность, мы обязаны предусмотреть совместимость. Поэтому 2TMTP распространяется в двух форматах:</p><ol><li>Самостоятельный протокол;</li><li>Расширения протокола SMTP. Дело в том, что в начале сессии eSMTP оба хоста «знакомятся», обмениваясь методами, которые могут применить на одной и другой стороне. Если найдено пересечение, то можно продолжить взаимный диалог. Если оба хоста заявили о поддержке 2TMTP, то оба переходят на взаимодействие по предложенному протоколу.</li></ol><p>Таким образом достигается расширенная функциональность. Тем же, кто этого не умеет, придётся довольствоваться архаичными свойствами.</p>]]></content:encoded>
    </item>
    <item>
      <title>ИИ научили красть информацию с монитора по излучению HDMI-кабеля</title>
      <link>https://tproger.ru/news/ii-nauchili-krast-informaciyu-s-monitora-po-izlucheniyu-hdmi-kabelya</link>
      <comments>https://tproger.ru/news/ii-nauchili-krast-informaciyu-s-monitora-po-izlucheniyu-hdmi-kabelya?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/ii-nauchili-krast-informaciyu-s-monitora-po-izlucheniyu-hdmi-kabelya</guid>
      <description><![CDATA[<p>Искусственный интеллект продолжает показывать себя как отличный инструмент для хакинга и взлома. На этот раз его использовали для перехвата изображения с монитора</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/ii-nauchili-krast-informaciyu-s-monitora-po-izlucheniyu-hdmi-kabelya">ИИ научили красть информацию с монитора по излучению HDMI-кабеля</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Хакеры]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 29 Jul 2024 03:51:06 GMT</pubDate>
      <content:encoded><![CDATA[<p>Электромагнитное излучение, исходящее от кабеля между компьютером и монитором, может быть перехвачено и расшифровано с помощью ИИ, чтобы показать, что именно отображается на экране.</p><p>Подобные атаки, вероятно, уже происходят в реальном мире, утверждает команда исследователей.</p><h2>Историческая справка</h2><p>Ранее соединение между компьютерами и мониторами было полностью аналоговым, однако сегодня оно преимущественно цифровое и передает данные в бинарном виде через кабель HDMI.</p><p>При передаче сигнала через провод всегда есть определенная утечка электромагнитного излучения. Для аналоговых сигналов это можно было относительно легко считать, что и делали хакеры.</p><h2>Современные методы и новые риски</h2><p>Атаки, использующие это явление, известны под названием TEMPEST и являются стандартом АНБ США для экранирования проводов, как раз с целью предотвращения их использования.</p><p>Цифровые сигналы более сложные и содержат большее число данных в сложных форматах, что затрудняет их расшифровку, даже несмотря на легкость их перехвата.</p><p>Федерико Ларрока из Университета Республики в Монтевидео, Уругвай, и его коллеги разработали модель ИИ, которая может реконструировать цифровые сигналы, перехваченные на расстоянии нескольких метров.</p><p>ИИ обучался с использованием набора совпадающих оригинальных и перехваченных сигналов.</p><h2>Эффективность атаки</h2><p>Для оценки эффективности атаки, команда использовала софт для захвата текста на восстановленном изображении и сравнила полученный текст с оригинальным изображением экрана.</p><p>В процессе перехвата около 30% символов были интерпретированы неправильно, но это достаточно низкий показатель, чтобы люди могли прочитать большую часть текста, утверждает команда.</p><p>Таким образом, около 70% изначального текста, при использовании перехвата через ИИ, вполне читаемы и понятны.</p><h2>Способы реализации атаки</h2><p>С помощью этой техники, хакеры могут шпионить за экраном, когда пользователь вводит личные данные, логины для банковских счетов или зашифрованные сообщения.</p><p>Хакеры могут перехватывать сигналы, находясь снаружи здания с антенной, которая захватывает изображения в реальном времени.</p><h2>Меры предосторожности</h2><ul><li><b>    Экранирование помещений:</b> использование специальных материалов для защиты от электромагнитного излучения.</li><li><b>Безопасное расположение оборудования:</b> размещение чувствительных устройств в зонах, недоступных для потенциальных перехватчиков.<br /></li><li><b>Регулярные проверки:</b> проведение аудитов безопасности для выявления и устранения возможных уязвимостей.<br /></li></ul><p>Эти меры помогут снизить риски утечек информации через электромагнитное излучение, обеспечив дополнительный уровень защиты данных.</p>]]></content:encoded>
    </item>
    <item>
      <title>3 простых способа ускорить код на Python</title>
      <link>https://tproger.ru/articles/3-prostyh-sposoba-uskorit-kod-na-python</link>
      <comments>https://tproger.ru/articles/3-prostyh-sposoba-uskorit-kod-na-python?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Вика Овсянникова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/3-prostyh-sposoba-uskorit-kod-na-python</guid>
      <description><![CDATA[<p>Если вы разрабатываете на Python, наверняка задумывались о том, как ускорить код. В статье разбираем три способа, которые помогут в этом.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/3-prostyh-sposoba-uskorit-kod-na-python">3 простых способа ускорить код на Python</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 26 Sep 2023 09:10:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Всем добрый день, меня зовут Даниил, я backend-разработчик из департамента IT Kokoc Group.</p><p>Python — это мощный и гибкий язык программирования. Однако из-за динамической типизации и интерпретируемости его производительность оставляет желать лучшего. И наверное, каждый, кто разрабатывает на нём продолжительное время, задавался вопросом, как ускорить код на Python. В этой статье рассмотрим три способа на примере одного кейса.</p><h2>Кейс для ускорения кода на Python</h2><p>Рассмотрим простую функцию, которая вычисляет сумму квадратов элементов большого списка чисел.</p><figure><img src="https://media.tproger.ru/user-uploads/75379/2023-10-04/fcdb6739-4eb6-4726-bb85-ef1ffff107c6.jpeg" alt="" /><figcaption>В этом примере мы используем стандартный подход с помощью встроенной функции sum и генератора списка</figcaption></figure><p>А теперь применим техники ускорения кода и понаблюдаем, как каждая из них отразится на скорости выполнения программы.</p><h3>1. List comprehension</h3><figure><img src="https://media.tproger.ru/user-uploads/75379/2023-09-20/6ba7a771-f874-4fdb-8a07-51eea39b3d84.png" alt="" /></figure><p>List comprehension — эффективный способ создавать и обрабатывать списки в одной строке. В Python он работает быстрее, чем традиционный цикл for, потому что весь процесс в нём оптимизирован и протекает внутри интерпретатора.</p><p>List comprehensions обычно вызывают меньше методов, чем for. Второй для каждой итерации вызывает метод append, что создаёт дополнительную нагрузку и обновляет состояние переменной на каждой итерации. А list comprehension создаёт новый список сразу, такой подход может быть более эффективным.</p><p>Важно отметить, что, хотя list comprehension обычно быстрее, его не всегда следует использовать. Если вы пытаетесь сделать что-то сложнее обычного преобразования данных, он может быть тяжеловат для понимания. Ясный и читаемый цикл for может быть лучшим выбором.</p><h3>2. Map() и lambda-функции</h3><figure><img src="https://media.tproger.ru/user-uploads/75379/2023-09-20/8bda3cf7-62a8-47a1-b8bd-645622b11872.png" alt="" /></figure><p>map() — встроенная функция, которая всегда используется в комбинации с итерируемой последовательностью, в данном случае со списком. Она идёт по каждому элементу последовательности (то есть к каждому объекту из списка) и применяет к нему функцию, которую приняла первым позиционным аргументом.</p><p>map() реализована на более быстром Си. И, как и list comprehension, оптимизирована на уровне интерпретатора Python. То есть при её использовании вы также передаёте всю работу интерпретатору, который оптимизирует выполнение операции.</p><p>Кроме того, map() в Python возвращает итератор, а не список. А итераторы — более эффективный способ обработки больших объёмов данных. Они не требуют загрузки всего набора данных в память сразу, а генерируют каждый элемент по мере необходимости. Это значительно снижает потребление памяти, особенно при работе с большими наборами данных.</p><p>Это также связано с принципом «ленивого вычисления»: итератор, возвращённый функцией map(), вычисляет каждый элемент «на лету» и только при необходимости.</p><p>Lambda-функции в Python — это анонимные функции, которые можно определить прямо в месте использования. То есть вместо того чтобы задавать отдельную именованную функцию через def, можно написать короткую лямбду — прямо в вызове map().</p><h3>3. NumPy и Pandas</h3><figure><img src="https://media.tproger.ru/user-uploads/75379/2023-09-20/3b3cacdf-018e-425c-8fc7-0318d04f77bd.png" alt="" /></figure><p>NumPy — это мощная библиотека, которая предоставляет объекты массивов N-мерного массива с эффективными операциями. При работе с большими массивами данных NumPy может быть намного эффективнее стандартных списков Python благодаря оптимизированным и векторизованным операциям.</p><figure><img src="https://media.tproger.ru/user-uploads/75379/2023-09-20/5a63f53e-a6ff-40b4-a9f4-1d7a99c08702.png" alt="" /></figure><p>Pandas — библиотека, предоставляющая эффективные структуры данных и инструменты анализа данных.</p><p>Фактически это надстройка над NumPy. Так что для ускорения кода логично использовать ту библиотеку, которая уже инсталлирована в проекте.</p><p>В основном NumPy и Pandas используют для работы с таблицами, когда нужно, допустим, выгрузить Excel-таблицу или рассортировать ячейки. Другие сферы — компьютерное зрение, векторная геометрия и так далее.</p><p>Код, в котором используют NumPy и Pandas, часто работает быстрее, чем аналогичный, но написанный с использованием стандартных функций и структур данных Python. И вот по каким причинам:</p><ol><li><b>Большая часть библиотек NumPy и Pandas написана на Cи и C++</b>. Благодаря этому скорость выполнения выше.</li><li><b>Векторизованные операции</b> выполняются сразу над массивами данных, а не поэлементно. Это обеспечивает значительное увеличение производительности, особенно при работе с большими объёмами данных.</li><li><b>Эффективное использование памяти.</b> NumPy и Pandas используют эффективные структуры данных, которые занимают меньше памяти и позволяют выполнять операции быстрее.</li><li><b>Функции оптимизированы</b> для быстрого выполнения на больших объёмах данных.</li></ol><h2>Результаты</h2><p>Время выполнения каждого подхода будет зависеть от машины и конкретного случая, но ориентировочно можно представить следующие результаты:</p><ul><li>стандартный подход: 0.25 секунды;</li><li>map и lambda: 0.18 секунды;</li><li>list comprehension: 0.17 секунды;</li><li>NumPy: 0.006 секунды;</li><li>Pandas: 0.006 секунды.</li></ul><p>Как видно, оптимизация может значительно ускорить код на Python. Однако не стоит забывать, что оптимальность любого подхода зависит от конкретного случая, и не всегда нужно стремиться к максимальной скорости исполнения в ущерб читаемости и поддерживаемости (list comprehension, внутри которого ещё два list comprehension, map и лямбда-функции — и всё это в одну строку, конечно, ускорит код, но прочитать его будет сложно).</p><p>В большинстве случаев выбор должен основываться на том, какой вариант делает код более понятным и поддерживаемым.</p>]]></content:encoded>
    </item>
    <item>
      <title>Хакеры удалили с YouTube самые просматриваемые музыкальные клипы</title>
      <link>https://tproger.ru/news/youtube-despacito-hacked</link>
      <comments>https://tproger.ru/news/youtube-despacito-hacked?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Светлана Хачатурян]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/youtube-despacito-hacked</guid>
      <description><![CDATA[<p>Хакеры удалили с YouTube клип Despacito и другие популярные видео, заменив их кадром из «Бумажного дома»; сервис затем восстановил ролики.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/youtube-despacito-hacked">Хакеры удалили с YouTube самые просматриваемые музыкальные клипы</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 10 Apr 2018 12:40:18 GMT</pubDate>
      <content:encoded><![CDATA[<p>Злоумышленники организовали атаку на YouTube, в ходе которой с ресурса были удалены несколько популярных музыкальных видеоклипов. В их числе — ролик на песню <a href="https://youtu.be/kJQP7kiw5Fk">Despacito</a> с более чем 5 млрд просмотров.</p><p>Вместо клипов зрителям демонстрировался кадр из <a href="https://www.kinopoisk.ru/film/bumazhnyy-dom-2017-1046206/">сериала</a> «Бумажный дом» про преступную группировку, решившую ограбить монетный двор Испании.</p><figure><img src="https://media.tproger.ru/uploads/2018/04/401705D3-28BD-4D38-8C7B-466EC7589EE8.jpeg" alt="" /></figure><h3>Кто и зачем?</h3><p>В Twitter объявились хакеры Prosox и Kuroi’sh, назвав себя зачинщиками происшествия.</p><p>Это просто прикол, просто запускаю скрипт <i>youtube-change-title-video </i>и пишу «взломан», не судите, я люблю YouTube.</p><p>На момент написания новости сервис Youtube восстановил ролик Despacito, а также несколько других видеоклипов.</p><p>Это не первый случай компрометации сервиса. Напомним, что в конце марта злоумышленникам <a href="https://tproger.ru/news/youtube-malvertising/">удалось запустить</a> на YouTube заражённые майнерами рекламные ролики.</p>]]></content:encoded>
    </item>
    <item>
      <title>В Сеть выложили коды, запускающие DDoS-атаки через серверы Memcached</title>
      <link>https://tproger.ru/news/memcached-proof-of-concept</link>
      <comments>https://tproger.ru/news/memcached-proof-of-concept?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Светлана Хачатурян]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/memcached-proof-of-concept</guid>
      <description><![CDATA[<p>Независимые разработчики опубликовали три разных варианта осуществления атак через заражённые серверы Memcached. Небольшие программы запустить у себя может любой желающий.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/memcached-proof-of-concept">В Сеть выложили коды, запускающие DDoS-атаки через серверы Memcached</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 08 Mar 2018 08:02:07 GMT</pubDate>
      <content:encoded><![CDATA[<p>Заинтересованные специалисты опубликовали собственные варианты реализации DDoS-атак через <a href="https://tproger.ru/news/ddos-atacks-via-memcached/">заражённые</a> серверы Memcached. Массовая злоумышленная кампания захватила уже более 17 000 IP-адресов и до сих пор не ликвидирована. Атаки <a href="https://tproger.ru/news/new-ddos-attack-record-for-1-7-tbps/">достигают</a> рекордных размеров.</p><h3>Proof-of-Concept</h3><p>Всего исследователи представили три различных способа использовать скомпрометированные устройства:</p><ul><li>скрипт на языке Python под названием Memcrashed, сканирующий поисковую систему Shodan на наличие IP захваченных серверов Memcached и позволяющий запускать DDoS-атаку на любое желаемое устройство буквально за несколько секунд:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/f5ec1c58-7698-443f-9b6a-208c300bb71a.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/5820c972-19c1-41ce-998b-b898019ec8b0.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/df465d04-05a3-48f2-bd6c-77eb36f1ddbd.png" alt="" /></figure><ul><li>код на Си из репозитория Pastebin, опубликованный вместе со списком из 17 000 IP уязвимых серверов и извлекающий из него адреса для проведения атаки:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/7e2b2836-eee3-461d-8001-9976cfd9bc8b.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/b33a8de7-1230-48f7-a9fe-2626cf29edcc.png" alt="" /></figure><ul><li>небольшой эксплойт, уместившийся в один твит:</li></ul><figure><img src="https://media.tproger.ru/user-uploads/101078/2024-08-06/6cb7edf5-3eb9-4f11-9f48-7638a2678cdb.png" alt="" /></figure><p>Memcached-кампания пока только расширяется. Напомним, что несколько дней назад жертвой атак <a href="https://tproger.ru/news/memcached-ddos-github/">стал</a> GitHub — наплыв запросов «положил» его на 9 минут.</p>]]></content:encoded>
    </item>
    <item>
      <title>Доступ к данным 1,3 млрд человек из индийской национальной ID-базы «слили» за 8 $</title>
      <link>https://tproger.ru/news/indian-national-id-database-breached</link>
      <comments>https://tproger.ru/news/indian-national-id-database-breached?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Светлана Хачатурян]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/indian-national-id-database-breached</guid>
      <description><![CDATA[<p>Административный доступ к индийской базе «Адхар» получил покупатель за 500 рупий, примерно 8 $, а сама система хранит персональные данные граждан.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/indian-national-id-database-breached">Доступ к данным 1,3 млрд человек из индийской национальной ID-базы «слили» за 8 $</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 06 Jan 2018 13:44:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>В 2010 году Индия начала кампанию по сбору персональной информации своих граждан для наполнения национальной базы данных под названием «Адхар». На сегодняшний день идентификационная БД содержит имена, адреса проживания, даты рождения, номера телефонов, сканы отпечатков всех пальцев и радужки глаза и другие детали персональной информации практически всех жителей страны. 3 января, по <a href="https://www.buzzfeed.com/pranavdixit/indias-national-id-database-with-private-information-of?utm_term=.ilWK6MjZj#.cigZdGpDp">сообщению</a> BuzzFeed, база была взломана.</p><h3>Что произошло?</h3><p>Индийская газета Tribune, <a href="http://www.tribuneindia.com/news/nation/rs-500-10-minutes-and-you-have-access-to-billion-aadhaar-details/523361.html">опубликовала</a> отчет, в котором описала, как репортеры заплатили 500 рупий (приблизительно 8 $) за секрет человеку, которому удалось взломать национальную систему. Назвавшийся Анилом Кумаром (Anil Kumar) мужчина сообщил, что смог создать особую пару «логин-пароль», открывающую доступ к данным практически 1,2 млрд индийцев путем ввода уникального 12-значного персонального кода «Адхар». Региональные сотрудники Уникального Идентификационного Органа Индии (UIDAI), ответственного за «Адхар», рассказали Tribune, что этот доступ «нелегален» и является «серьезным нарушением национальной безопасности».</p><p>Второй отчет, <a href="https://www.thequint.com/news/india/exclusive-aadhaar-dirty-secret-out-add-anyone-as-data-admin">опубликованный</a> индийским новостным сайтом Quint, обнародовал информацию, согласно которой любой человек может создать аккаунт администратора и получить доступ к базе, пока он приглашен существующим администратором.</p><h3>Другое мнение</h3><p>4 января индийская партия Narendra Modi-led Bharatiya Janata назвала новость Tribune фейком.</p><p>По словам BuzzFeed, в ответном письме UIDAI «отрицает» отчет Tribune, заявляя, что «данные «Адхары», включая биометрическую информацию, абсолютно надежны и защищены». Представители агентства добавили, что газета злоупотребила поисковым механизмом базы данных, доступным только правительству, и примет законные меры против лиц, ответственных за организацию несанкционированного доступа.</p><blockquote>Заявление об обходе или обмане системы «Адхар» совершенно не обоснованы. Данные базы надежно засекречены. Дата-центры UIDAI — это инфраструктура высочайшей важности, поэтому они защищены в соответствии с возможностями высоких технологий, отвечающих лучшим стандартам безопасности, а также законом.</blockquote><h3>«Просто для себя»</h3><p>Репортерам BuzzFeed New удалось отследить Кумара (имя оказалось псевдонимом). Он рассказал, что на прошлой неделе продал доступ к «Адхаре» еще 7 лицам помимо репортера Tribune за ту же цену. По словам мужчины, он не знал, что своими действиями компрометирует частную жизнь людей и переступает закон.</p><p>Я заплатил 6000 рупий (примерно 95 $) анонимному человеку из группового чата в WhatsApp, в котором я состоял, чтобы он создал логин и пароль к «Адхаре» для меня. Мне сказали, что теперь я могу создавать столько логинов и паролей для доступа к базе, сколько захочу. Вот я и продал каждый, чтобы вернуть свои 6000 рупий.</p><p>Многие жители Индии крайне возмущены фактом существования «Адхары». Несмотря на то, что внесение личной информации в базу добровольно, государство буквально вынуждает граждан участвовать в этой кампании, «выуживая» их данные из всех возможных источников (банки, сотовые операторы и т. п.).</p>]]></content:encoded>
    </item>
    <item>
      <title>Жесткие диски оказались уязвимы к звуковым атакам</title>
      <link>https://tproger.ru/news/hdd-acoustic-attacks</link>
      <comments>https://tproger.ru/news/hdd-acoustic-attacks?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Светлана Хачатурян]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/hdd-acoustic-attacks</guid>
      <description><![CDATA[<p>Звуковые волны определённой частоты создают вибрации в HDD и останавливают чтение и запись, из-за чего могут зависнуть ПК и системы видеонаблюдения.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/hdd-acoustic-attacks">Жесткие диски оказались уязвимы к звуковым атакам</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 30 Dec 2017 14:35:13 GMT</pubDate>
      <content:encoded><![CDATA[<p>С помощью грамотно настроенных звуковых волн злоумышленники могут прерывать нормальную работу жесткого диска, создавая временный или даже постоянный отказ в обслуживании, <a href="https://www.bleepingcomputer.com/news/security/acoustic-attacks-on-hdds-can-sabotage-pcs-cctv-systems-atms-more/">сообщает</a> Bleeping Computer. Эта уязвимость может выводить из строя системы видеонаблюдения и «замораживать» работу нагруженного компьютера.</p><h3>Как это происходит?</h3><p>Главный принцип атаки — способность звуковых волн определенной частоты создавать вибрации в элементах хранения данных HDD. Поскольку на жестких дисках обычно «утрамбовывается» огромное количество информации, магнитные пластины специально запрограммированы на остановку всех операций чтения/записи во время тряски. Это сделано во избежание механических повреждений пластин и потери данных.</p><h3>Живой пример</h3><p>Несколько дней назад ученые из Принстонского универститета и университета Пердью опубликовали исследование, расширяющее рамки понимания обнаруженной проблемы. Группа ученых сконструировала специальное тестовое пространство для звуковой атаки на HDD с разных углов. При этом велся постоянный учет частоты звуковых волн, времени атаки, расстояния от источника звука до диска, а также углов «бомбардировки», под которыми устройство прекращало нормальную работу.</p><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/d980b848-f1ce-402e-8c6a-b8ed249eb8d0.png" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/33794/2024-02-19/efb59335-13dc-4617-bcc8-c0de62cc143d.png" alt="" /></figure><p>Эти манипуляции позволили исследователям определить оптимальный размах частот для четырех жестких дисков Western Digital. По словам ученых, определить те же показатели для устройств других производителей не составит труда.</p><figure><img src="https://media.tproger.ru/uploads/2017/12/HDD-DoS-Attack-Frequencies.png" alt="" /></figure><p>Исследователи утверждают, что любой злоумышленник, генерирующий звуковые сигналы вблизи жесткого диска, запросто может перехватить управление накопителем и тем самым подорвать работу завязанной на нем системы.</p><h3>Способы атаки</h3><p>Звуковые сигналы можно доставить до жесткого диска несколькими способами.</p><blockquote>Злоумышленники могут распространять звук посредством стороннего динамика или же использовать динамики, находящиеся в непосредственной близости от цели. С этой стороны у хакеров есть потенциальное преимущество во взломе мультимедийного программного обеспечения устройства. Также вредоносные сигналы можно распространять обманным путем: встраивать их в электронные письма, веб-сайты или даже телевизионную рекламу.</blockquote><p>Вне зависимости от выбранного способа доставки звуковой атаки, успешность подобной кампании зависит от целой серии условий. Работоспособность и качество атаки на жесткий диск определяются:</p><ul><li>расстоянием от источника звука до цели;</li><li>временем воздействия;</li><li>наличием оператора-человека вблизи атакуемого устройства (звуки, поражающие HDD, находятся в диапазоне слышимости человеческого уха).</li></ul><h3>Атака на систему видеонаблюдения</h3><blockquote>Примерно через 230 секунд после начала звуковой атаки, на экране монитора высветилось окно с предупреждением «Диск не найден». После остановки сигнала мы попытались воспроизвести видео, записываемое камерами в момент атаки, и обнаружили, что запись была прервана. Для восстановления нормальной работы пришлось перезагрузить видеорегистратор, однако весь отснятый материал был безвозвратно утерян.</blockquote><h3>Атака на ПК</h3><p>Второй эксперимент проводился над жесткими дисками персональных компьютеров. Исследователи направили звуковую волну частотой 9,1 кГц прямо в вентиляционное отверстие диска с расстояния 25 см.</p><p>Это приводило к «самым разнообразным сбоям в работающем ПК», включая даже «синий экран смерти» при длительных звуковых атаках.</p><figure><img src="https://media.tproger.ru/uploads/2017/12/pc-attack-results.png" alt="" /></figure><p>Подобные атаки весьма сложны в реализации, поэтому они, скорее всего, не будут очень востребованы среди хакеров в «повседневности», сообщают исследователи. Однако владельцам важных данных все-таки стоит проработать способы защиты от таких нападений. С более подробной информацией о результатах проведенных экспериментов и детальным обзор ситуации можно ознакомиться в официальном <a href="https://arxiv.org/pdf/1712.07816.pdf">отчете</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>[[][[]]+[]][+[]][++[+[]][+[]]] — это «n» в JavaScript</title>
      <link>https://tproger.ru/articles/n-in-javascript</link>
      <comments>https://tproger.ru/articles/n-in-javascript?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/n-in-javascript</guid>
      <description><![CDATA[<p>Недавно на Reddit появился пост с объяснением, почему конструкция [[][[]]+[]][+[]][++[+[]][+[]]] в языке JavaScript вычисляется как символ «n».</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/n-in-javascript">[[][[]]+[]][+[]][++[+[]][+[]]] — это «n» в JavaScript</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Юмор]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 04 Sep 2017 19:29:32 GMT</pubDate>
      <content:encoded><![CDATA[<p>Недавно на Reddit появился <a href="https://www.reddit.com/r/ProgrammerHumor/comments/6xzcgb/is_n_in_javascript/">пост</a> с объяснением, почему конструкция [[][[]]+[]][+[]][++[+[]][+[]]] в языке JavaScript вычисляется как символ «n». Переводим его для вас.</p><p>Итак, начнём с пустого массива:</p><p>[]</p><p>Теперь получим доступ к элементу пустого массива:</p><p>[][]</p><p>Какому элементу? Пусть это будет элемент с индексом пустого массива:</p><p>[][[]]</p><p>Это значение не определено, т.е. равно undefined, но если добавить к нему пустой массив, то получится строка «undefined»:</p><p>[][[]]+[]</p><p>Обернём её массивом:</p><p>[[][[]]+[]]</p><p>Теперь попробуем получить доступ к буквам этой строки. Для начала нам нужно получить доступ к самой строке внутри массива:</p><p>[[][[]]+[]][0]</p><p>А ведь ноль можно получить, если преобразовать пустой массив к числу:</p><p>[[][[]]+[]][+[]]</p><p>Буква «n» вторая в слове «undefined», значит, индекс у неё 1:</p><p>[[][[]]+[]][+[]][1]</p><p>Но как нам получить 1? Конечно же, увеличить на единицу 0, который мы уже научились получать ранее:</p><p>++[0][0]</p><p>И, как и раньше, нули тоже можно записать через скобки:</p><p>++[+[]][+[]]</p><p>Итак, собираем всё вместе и получаем:</p><p>[[][[]]+[]][+[]][++[+[]][+[]]]</p><p>Больше почитать про похожие трюки можно в <a href="https://tproger.ru/translations/js-magic-with-6-symbols/">нашей статье</a> про магию JavaScript — в ней рассказывается, что интересного можно сделать, используя всего 6 символов.</p>]]></content:encoded>
    </item>
    <item>
      <title>Инструкция: получаем число подписчиков аккаунта Twitter без использования Twitter REST API</title>
      <link>https://tproger.ru/articles/twitter-followers-no-api</link>
      <comments>https://tproger.ru/articles/twitter-followers-no-api?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Антон]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/twitter-followers-no-api</guid>
      <description><![CDATA[<p>О хаке, позволяющем одним запросом получить число подписчиков аккаунта Twitter без OAuth-идентификации приложения и других ограничений Twitter REST API.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/twitter-followers-no-api">Инструкция: получаем число подписчиков аккаунта Twitter без использования Twitter REST API</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 03 Jul 2017 14:52:50 GMT</pubDate>
      <content:encoded><![CDATA[<p>Twitter API недружелюбен для новичков, и «по-быстрому» одним запросом получить через него число подписчиков аккаунта не получится. Однако существует интересный хак, основанный на использовании <a href="https://web.archive.org/web/20160705114006/https://about.twitter.com/resources/buttons">кнопки «Follow»</a>.</p><p>Запрос к этому адресу позволяет получить необходимую информацию об аккаунте в формате JSON:</p><blockquote>https://cdn.syndication.twimg.com/widgets/followbutton/info.json?screen_names=tproger</blockquote><p>На момент публикации этого материала на приведенный выше запрос приходит ответ со следующей информацией об <a href="https://twitter.com/tproger">аккаунте Tproger в Twitter</a>:</p><p>Указывая в приведенном выше запросе необходимый вам набор screen_names (их может быть больше одного, несколько значений нужно указывать через запятую), вы можете получить информацию об интересующих вас аккаунтах. Никаких дополнительны ключей доступа не требуется. Также у этого способа нет ограничения на число запросов.</p>]]></content:encoded>
    </item>
    <item>
      <title>11 полезных приёмов в JavaScript</title>
      <link>https://tproger.ru/translations/11-useful-javascript-hacks</link>
      <comments>https://tproger.ru/translations/11-useful-javascript-hacks?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/11-useful-javascript-hacks</guid>
      <description><![CDATA[<p>Подборка приёмов языка JavaScript, которые сокращают объём кода и оптимизируют его, — среди них конвертация в Boolean двойным отрицанием.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/11-useful-javascript-hacks">11 полезных приёмов в JavaScript</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 17 Apr 2017 17:15:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>В этой статье мы расскажем об 11 весьма полезных приёмах в языке JavaScript. Они помогут вам сократить объём кода и оптимизировать его. Итак, начнём.</p><h2>Конвертация в Boolean при помощи оператора !!</h2><p>Порой нам нужно проверить, существует ли значение переменной и валидно ли оно, чтобы в этих случаях считать их верными, то есть равными true. Для этого можно применить к переменной оператор двойного отрицания !!, который автоматически меняет любой тип данных на логический (boolean) и возвращает false только в тех случаях, когда переменная принимает одно из следующих значений: 0, null, "", undefined или NaN. Вот простой пример:</p><p>Если значение account.cash больше нуля, account.hasMoney будет равна true.</p><h2>Конвертация в Number при помощи оператора +</h2><p>Удивительно простой приём! Работает он только со строками, а во всех остальных случаях возвращает NaN (Not a Number). Взглянем на пример:</p><p>Эта магия также работает с типом Date, возвращая <a href="https://ru.wikipedia.org/wiki/Timestamp">timestamp</a>:</p><p>Раз уж речь зашла о магии, советуем прочитать <a href="https://tproger.ru/translations/js-magic-with-6-symbols/">нашу статью</a>, которая расскажет о настоящей магии JavaScript.</p><h2>Упрощённая запись условных выражений</h2><p>Допустим, у нас есть подобный код:</p><p>Его можно сократить, поместим оператор &amp;&amp; между переменной (значение которой проверяется) и функцией. Вот так можно записать наш код:</p><p>Аналогично можно проверить, есть ли у объекта те или иные атрибуты и методы:</p><p>Это связано с так называемой короткой логикой: если левый операнд &amp;&amp; равен false, то правый операнд даже не будет вычислен, потому что и так ясно, что все выражение ложно. И если правым операндом является функция, то она не будет вызвана.</p><h2>Значения по умолчанию при помощи оператора ||</h2><p>В ES6 есть возможность задать значение аргумента по умолчанию. Для того, чтобы воспроизвести эту фичу в старых браузерах, можно использовать оператор ||, добавив в качестве второго параметра значение по умолчанию. Если первый параметр вернёт false, будет использоваться второй. Вот пример:</p><p>Подробнее о стандарте ES6 можно почитать в наших статьях:</p><ul><li>Часть первая: <a href="https://tproger.ru/translations/es6-cheatsheet-1/">let / const, блоки, стрелочные функции, строки, деструктуризация, модули, параметры, классы</a>;</li><li>Часть вторая: <a href="https://tproger.ru/translations/es6-cheatsheet-2/">мэпы, слабые мэпы, обещания, генераторы, async / await, геттеры / сеттеры, символы</a>.</li></ul><h2>Распознавание свойств объекта</h2><p>Приём очень полезен, когда нужно проверить, существует ли тот или иной атрибут или метод. Также он может пригодиться и при кроссбраузерной вёрстке. Представим, что вам нужно написать код, совместимый с древним Internet Explorer 6, и вы хотите использовать document.querySelector() для получения элементов по идентификаторам. Но в IE6 такой функции не существует, поэтому нужно добавить проверку:</p><p>В этом примере мы можем использовать document.getElementById() как запасной вариант, если в объекте-документе нет функции querySelector.</p><h2>Получение последнего элемента массива</h2><p>Наверняка вы знакомы с методом Array.prototype.slice(begin, end): с его помощью можно вырезать из массива кусок, задавая его границы begin и end. Если вы не зададите значение end, то функция автоматически задаст максимально возможное значение. Но немногие знают, что этот метод может принимать и отрицательные значения — если begin равен отрицательному числу, вы получите последние элементы массива:</p><h2>Укорачивание массива</h2><p>Этот способ позволяет зафиксировать размер массива и удалить все лишние элементы. Например, у вас есть массив из 10 элементов, а вам нужны только первые 5. В таком случае достаточно одной простой команды: array.length = 5. Вот наглядный пример:</p><h2>Замена всех подстрок</h2><p>Метод String.replace() позволяет заменять подстроки при помощи <a href="https://tproger.ru/articles/regexp-for-beginners/">регулярных выражений</a>, но по умолчанию заменяется лишь первое вхождение подстроки. Тем не менее, вы можете исправить это, добавив /g в конец «регулярки»:</p><h2>Слияние массивов</h2><p>Если вам нужно объединить два массива, вы можете использовать метод Array.concat():</p><p>Однако он не подходит для слияния больших массивов, поскольку потребляет большое количество памяти, создавая новый массив. В этом случае лучше использовать Array.push.apply(arr1, arr2), что поместит второй массив в первый, сократив потребление памяти:</p><h2>Конвертация NodeList в массив</h2><p>Если вы вызовете document.querySelectorAll("p"), то наверняка получите массив элементов DOM, объект класса NodeList. Проблема в том, что у него нет таких полезных методов, как sort(), reduce(), map() и filter(). Чтобы активировать эти и другие полезные методы, вам нужно конвертировать NodeList в массив. Для этого нужно просто выполнить [].slice.call(elements):</p><h2>Перемешивание элементов массива</h2><p>Чтобы перемешать элементы массива, не используя сторонние библиотеки вроде Lodash, можно выполнить этот приём:</p><h2>Заключение</h2><p>Вы узнали несколько полезных приёмов, которые позволяют уменьшить JS-код. Многие из них используются в таких библиотеках, как, например, Lodash, Underscore.js и Strings.js. Если вы знаете другие приёмы, делитесь ими, и мы пополним нашу статью.</p>]]></content:encoded>
    </item>
    <item>
      <title>Обмен значений переменных: разбор популярных способов решения известной задачи с IT-собеседований</title>
      <link>https://tproger.ru/problems/popular-ways-to-swap</link>
      <comments>https://tproger.ru/problems/popular-ways-to-swap?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Антон]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/popular-ways-to-swap</guid>
      <description><![CDATA[<p>Разбор популярного вопроса с IT-собеседований начинается с ошибочной реализации, в которой обе переменные получают одно и то же значение.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/popular-ways-to-swap">Обмен значений переменных: разбор популярных способов решения известной задачи с IT-собеседований</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Собеседование]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 27 Mar 2017 18:10:10 GMT</pubDate>
      <content:encoded><![CDATA[<p>Самый простой способ взаимно менять значения переменных — использование swap(a, b) или же аналогичного стандартного метода. Тем не менее, важно понимать как работает операция по обмену значений двух переменных, что мы покажем на нескольких примерах.</p><p>Для начала продемонстрируем неправильную реализацию и выясним, что в ней не так.</p><h3>Ошибочная реализация</h3><p>Если вы попытаетесь выполнить обмен значений этим способом, то увидите, что теперь в обеих переменных хранится значение переменной b. Происходит это ввиду построчного выполнения кода. Первая операция присваивания сохраняет значение переменной b в переменную a. Затем вторая — новое значение a в b, иными словами значение b в b. Таким образом, мы полностью теряем содержание контейнера a.</p><p>Теперь обратимся к правильной реализации.</p><h3>С использованием буфера</h3><p>Буфером в данном случае называется дополнительная используемая память. Давайте разберёмся зачем она здесь нужна. Если помните, в неправильной реализации мы потеряли значение переменной a после первой операции присваивания, в связи с чем в обеих доступных переменных осталось значение b. Чтобы этого избежать нам понадобится ещё одна переменная — c. В таком случае правильный алгоритм будет выглядеть так:</p><p>Для наглядности разберём его пошагово:</p><ol><li>Присваиваем переменной c значение переменной a. Сейчас в a записана a, в b — b, а в c — a.</li><li>Присваиваем переменной a значение переменной b. Теперь в a хранится b, в b — также b и в c — a.</li><li>Присваиваем переменной b значение переменной c. Сейчас в a находится старое значение b, в b — a, ну и в c остаётся a.</li></ol><p>Как вы видите, переменная c после выполнения алгоритма не нужна, поэтому далee в программе её можно не использовать и даже вовсе удалить из памяти.</p><p>Сразу стоит заметить, что это самое краткое и экономное решение задачи, но можно использовать и больше переменных, не так ли?</p><p>Нам повезло, что сейчас вопрос экономии оперативной памяти не стоит так остро, как 20-30 лет назад. Тем не менее, в те времена swap был востребован не меньше, поэтому умные люди нашли способ заменить значения двух переменных без ввода третьей.</p><h3>Арифметика</h3><h4>Сложение / вычитание</h4><p>Для лучшего восприятия снова разберём алгоритм построчно:</p><ol><li>Присваиваем переменной a сумму значений переменных a и b. Сeйчас в a записано значение a + b, а в b всё ещё b.</li><li>Переменной b присваиваем разность между новым значением переменной a и переменной b. В a также хранится a + b, но в b уже a.</li><li>Наконец, присваиваем переменной a результат вычитания b из обновлённого значения a. Получается, что в a теперь содержится b, а в b — a.</li></ol><p>Для C-подобных языков сокращённая запись этого алгоритма выглядит так:</p><h4>Умножение / деление</h4><p>Аналогичный способ решения задачи получается при замене сложения умножением и вычитания делением:</p><p>В сокращённом варианте:</p><h4>Вычитание / Сложение</h4><p>Вообще, в математике действие вычитания отсутствует и является сложением положительного и отрицательного чисел. Отсюда следует, что мы можем поменять местами операции сложения и вычитания:</p><p>Обратите внимание, что в последней строке знак у переменной a изменился, а саму строчку можно записать иначе: a = b - a;.</p><p>Такой же принцип можно использовать поменяв местами деление и умножение.</p><h4>Недостатки арифметического метода</h4><p>Главным недостатком является большее количество операций, в чём можно убедиться посчитав операции сложения, вычитания и присваивания. Тeм болee, что умножeниe и дeлeниe болee «дорогостящиe». Заметной потеря скорости становится в ситуации, когда трeбуeтся менять значения большого количества пeрeмeнных.</p><p>Второй важный нeдостаток это область применения — числа. Согласитесь, менять значения пeрeмeнных, содержащих объeкты попросту нe получится без перегрузки операции. Впрочeм, дажe с числами могут возникнуть проблемы — арифметика для вeщeствeнных чисeл можeт выполняться некорректно, что приведёт к неожиданному результату.</p><p>Eстeствeнно, существует и менее очевидный способ рeшeния задачи без использования дополнительной памяти. Он основан на свойствах логических операций и работает с битовым представлением числа, а значит быстрее арифметического метода.</p><h3>Битовые операции</h3><p>Данный алгоритм основан на следующем свойстве операции XOR («исключающее или»): a XOR b XOR a = b.</p><p>Для любитeлeй коротких записeй приведём код одной строчкой. XOR в C-подобных языках замeняeтся знаком ^:</p><p>Однако помните о <a href="http://alenacpp.blogspot.ru/2005/11/sequence-points.html">точках следования</a>. Из-за них этот код может вести себя непредсказуемо и давать разные результаты, поэтому никогда не используйте его в production коде.</p><p>Обязательно посмотрите более подробный <a href="https://tproger.ru/problems/write-a-function-which-swaps-the-values-of-variables-without-temporary-variables/">разбор решения через битовые операции</a> от Г. Лакмана Макдауэлла, автора известного сборника задач с собеседований, который есть в <a href="https://tproger.ru/books/books-the-chosen-ones/">одной из наших книжных подборок</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>πfs: новая файловая система, с которой вам не придётся беспокоиться о данных</title>
      <link>https://tproger.ru/articles/pi-fs-never-worry-about-data-again</link>
      <comments>https://tproger.ru/articles/pi-fs-never-worry-about-data-again?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/pi-fs-never-worry-about-data-again</guid>
      <description><![CDATA[<p>Исходники πfs нашлись на GitHub: вместо места на диске используется число пи, а для сборки понадобятся пакеты autoconf, automake и libfuse.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/pi-fs-never-worry-about-data-again">πfs: новая файловая система, с которой вам не придётся беспокоиться о данных</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 15 Mar 2017 19:51:43 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вчера неофициально отмечался <a href="https://ru.wikipedia.org/wiki/День_числа_пи">день числа пи</a>, и мы нашли на GitHub <a href="https://github.com/philipl/pifs">исходники</a> интересной файловой системы πfs. Вместо того, чтобы тратить место на жёстком диске, храните данные в π! В этом числе содержится любой доступный файл, поэтому у вас никогда не кончится место, да и сжатие практически стопроцентное 🙂</p><p>πfs очень легко собрать. Сперва вам нужно установить пакеты autoconf, automake и libfuse. Например, на Debian это делается так:</p><p>πfs очень просто использовать:</p><p>где metadata directory — это место, где πfs должна хранить метаданные (имена файлов и их местоположения в π), а mountpoint — это <a href="https://ru.wikipedia.org/wiki/Точка_монтирования">точка монтирования</a> вашей обычной файловой системы.</p><h3>Но как связаны число π и мои данные?</h3><p>π (или «пи») — это одна из важнейших математических констант, которая обладает интересными свойствами (подробнее о них <a href="https://ru.wikipedia.org/wiki/Пи_(число)">можно узнать</a> на Википедии).</p><p>Одно из свойств заключается в том, что число π считается нормальным, то есть все цифры в его записи распределены нормально, и что эти цифры образуют <a href="https://en.wikipedia.org/wiki/Disjunctive_sequence">дизъюнктивную последовательность</a>, то есть в записи числа можно найти любую конечную последовательность цифр. В шестнадцатеричной системе счисления это свойство выполняется, значит, в π существуют все возможные файлы. Впервые этот факт <a href="http://www.netfunny.com/rhf/jokes/01/Jun/pi.html">был обнаружен</a> в 2001 году.</p><p>Теперь возникает вопрос: зачем тратить эксабайты на хранение этих данных, если их можно просто найти в π?</p><h3>И что, прям совсем любой?</h3><p>Именно! Любой, который создали вы, кто-то другой и который ещё вообще не создали! Нарушение авторских прав? Бросьте, это лишь несколько цифр числа π! Они всегда там были!</p><h3>Но как найти там мои данные?</h3><p>Если вы знаете, с какой по счёту цифры числа начинается ваш файл и его длину, его легко извлечь при помощи <a href="https://ru.wikipedia.org/wiki/Формула_Бэйли_—_Боруэйна_—_Плаффа">формулы Бэйли-Боруэйна-Плаффа</a>. Кроме того, её можно использовать для поиска той самой первой цифры.</p><p>Чем длиннее искомая последовательность, тем дольше её искать, поэтому есть смысл разбить файлы на небольшие блоки. В этой реализации для повышения производительности файлы разбиваются на отдельные байты, которые ищутся в π.</p><h3>Я нашёл свои байты, но как запомнить их местоположение?</h3><p>Ну, вы всегда можете их записать на листок бумаги — но почему бы не записать их в π? Более того, местоположения файлов в числе — это <a href="https://ru.wikipedia.org/wiki/Метаданные">метаданные</a>, и даже если вы их потеряете, сами данные останутся в π — куда им оттуда деться?</p><h3>Но почему она такая медленная? Файл в 400 строк записывался целых 5 минут!</h3><p>Это лишь прототип, но не стоит забывать про закон Мура 😉</p>]]></content:encoded>
    </item>
    <item>
      <title>Подборка неожиданного, странного, местами безумного кода: самые необычные программы из когда-либо написанных</title>
      <link>https://tproger.ru/translations/creepy-code-collection</link>
      <comments>https://tproger.ru/translations/creepy-code-collection?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/creepy-code-collection</guid>
      <description><![CDATA[<p>Регулярное выражение на Perl для проверки простого числа, выражение для дня недели и другие примеры кода, который ломает мозг даже опытным кодерам.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/creepy-code-collection">Подборка неожиданного, странного, местами безумного кода: самые необычные программы из когда-либо написанных</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Ruby]]></category>
      <category><![CDATA[Perl]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 14 Mar 2017 21:35:50 GMT</pubDate>
      <content:encoded><![CDATA[<p>Сегодня мы поговорим о самых странных программах, какие вы когда-либо видели. Настолько странных, что они сломают ваш мозг. Настолько маленьких, что не верится, что они работают. И настолько непонятных, что даже прошаренные кодеры начнут неистово гуглить.</p><p>Примечание Никогда не используйте такой код в реальных проектах — читаемость и поддерживаемость превыше всего.</p><h3>Уровень 0. Вступление</h3><p>Взгляните на этот милый код:</p><p>Это регулярное выражение написано на Perl и проверяет, является ли число простым. Вот <a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/check_prime.pl">полный код программы</a> для запуска. А вот <a href="https://tproger.ru/articles/quick-guide-to-perl/">наше руководство по Perl</a>, чтобы вы могли начать его изучать.</p><p>А это выражение выдаст день недели для заданной даты:</p><p>А как вам этот код на Java?</p><p>Чему будет равно i? Он вообще скомпилируется? Да уж…</p><p>А программа на гифке ниже — это <a href="https://tproger.ru/articles/quines">куайн</a> по имени qlobe, написанный на Ruby. Ну разве это не изумительно?</p><figure><img src="https://media.tproger.ru/uploads/2017/02/258441bc-c712-11e6-88bf-f8f02a028ad3.gif" alt="" /></figure><p>А эта — ну просто шедевр! Анимированный 3D-пончик, какая вкуснятина!</p><p>Вставьте этот код в адресную строку:</p><p>и оцените всю магию самостоятельно!</p><p>А вообще лучше ничего не копипастьте, <a href="https://tproger.ru/translations/dont-copy-paste-from-internet-to-terminal">особенно код для командной строки</a>, последствия могут быть неприятными.</p><p>Большую часть программ, приведённых ниже, вы вряд ли поймёте. Но описания по ссылкам помогут прояснить ситуацию. Для запуска этих программ вам может понадобится один из <a href="https://tproger.ru/digest/compile-code-online/">онлайн-компиляторов</a>, о которых мы рассказывали в одной из наших статей, например, ресурсы <a href="https://www.tutorialspoint.com/codingground.htm">TutorialsPoint-CodingGround</a> и <a href="https://repl.it/languages">repl.it</a> — там есть онлайн-редакторы кода и компиляторы.</p><h3>Уровень 1. Начинающий</h3><p><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/pyjava.java">pyjava.java</a> – Java-код, написанный, как на Python. Вычисляет факториалы больших чисел.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/one_line_swap.c">one_line_swap.c</a> – Странные однострочники, меняющие местами значения двух переменных.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/hello_world.java">hello_world.java</a> – Магическим образом выводит в консоли «hello world».<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/obfuscated.java">obfuscated.java</a> – Выводит в консоли «Hi!», но выглядит как большой бессмысленный комментарий.</p><h3>Уровень 2. Типичный</h3><p>Исходник – Описание</p><p><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/bitwise_arithmetic.c">bitwise_arithmetic.c</a> – Складывает и перемножает числа при помощи битовых операций.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/prefix2postfix.c">prefix2postfix.c</a> – Преобразует префиксную нотацию в постфиксную.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/sapin.c">sapin.c</a> – Выводит движущуюся новогоднюю ёлку.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/crazy_jvm.java">crazy_jvm.java</a> – Похоже, что JVM сошла с ума и выводит случайные числа.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/confusion.java">confusion.java</a> – Удивительно, но этот код компилируется и выводит 1.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/not_so_random.java">not_so_random.java</a> – Выведет (случайным образом!) 1 1 1 1 1 1 1 1 1 1.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/bangladesh.c">bangladesh.c</a> – Выводит карту Бангладеша.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/signature_prime.c">signature_prime.c</a> – Бесконечно (теоретически) выводит простые числа.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/day_of_week.c">day_of_week.c</a> – Вычисляет день недели для заданной даты.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/polyglot_so404.py.pl.rb.c.bf">polyglot_so404.py.pl.rb.c.bf</a> – Выводит 404 на Python, Perl, Ruby, C и Brainfuck.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/polyglot_quine.c.py.pl.rb">polyglot_quine.c.py.pl.rb</a> – Куайн, который работает в C, Python, Perl и Ruby.</p><h3>Уровень 3. Продвинутый</h3><p>Исходник – Описание</p><p><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/compound_eye.rb">compound_eye.rb</a> – Выводит анимированный узор.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/best_short_program.c">best_short_program.c</a> – Считывает число, записанное словами, и выводит его в десятичном виде.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/check_prime.pl">check_prime.pl</a> – Проверяет, является ли число простым, при помощи регулярного выражения.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/quine_signature.c">quine_signature.c</a> – Самый короткий код на Си, который печатает сам себя.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/clock_in1line.c">clock_in1line.c</a> – Выводит текущее время в виде ASCII-арта.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/japh.pl">japh.pl</a> – Выводит «just another perl hacker».<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/matrix_effect.html">matrix_effect.html</a> – Выводит экран Матрицы.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/pi_signature.c">pi_signature.c</a> – Вычисляет первые 15 тысяч знаков числа пи после запятой.</p><h3>Уровень 4. Просветлённый</h3><p>Исходник – Описание</p><p><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/mandelbrot_imager.py">mandelbrot_imager.py</a> – Создаёт множество Мандельброта (может работать до 20 минут!).<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/shortest_tetris.html">shortest_tetris.html</a> – Очень простой вариант Тетриса.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/qlobe.rb">qlobe.rb</a> – Выводит вращающийся глобус.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/animated_3d_doughnut.c">animated_3d_doughnut.c</a> – Показывает трёхмерный анимированный ASCII-пончик.<br /><a href="https://github.com/MinhasKamal/CreepyCodeCollection/blob/master/mandelbrot_flythrough.pl">mandelbrot_flythrough.pl</a> – Позволяет вращать, приближать, отдалять и прокручивать множество Мандельброта.</p><h3>Программы для ценителей</h3><p>Исходник – Описание</p><p><a href="https://rosettacode.org/wiki/Polyglot">octaglot.cob.pas.f77.c.ps.sh.pl.com</a> – Полиглот, выводит «hello polyglots» на 8 языках.<br /><a href="https://github.com/kenrube/Esopoly">esoteric_polyglot.mal.bf.ws.asdf.​123.spoon.excon</a> – Полиглот, написанный на 7 эзотерических языках.<br /><a href="https://github.com/KvanTTT/Freaky-Sources/blob/master/Patterns%20and%20Data/PalindromePolyglotQuine.cs.java">palindrome_polyglot_quine.cs.java</a> – Код-палиндром, компилируется в C# и Java и выводит сам себя.<br /><a href="https://github.com/mame/quine-relay">quine_relay.rb</a> – Программа-уроборос, написанная на 100 различных языках.</p><p>У многих программ есть обсуждения на сайтах <a href="https://stackoverflow.com/">StackOverflow</a>, <a href="https://www.quora.com/">Quora</a>, <a href="https://codegolf.stackexchange.com/">Programming Puzzles &amp; Code Golf </a>и <a href="https://news.ycombinator.com/news">Hacker News</a>.</p><p>Если вам понравилась эта подборка, то обязательно понравится ещё одна: <a href="https://github.com/MinhasKamal/CuteVirusCollection">CuteVirusCollection</a>. Будьте осторожны! Все программы оттуда немедленно перехватят контроль над системой, какой бы мощной она не была. Но поверьте, вирусы ещё никогда не были такими милыми.</p><h3>Вам не хватило странного кода? Вот ещё несколько подборок:</h3><ul><li>Рубрика <a href="https://tproger.ru/tag/good-hack/">«Красивый хак»</a> на нашем сайте;</li><li><a href="http://www.ioccc.org/years-spoiler.html">IOCCC</a>, <a href="http://www.pixelstech.net/article/1351185934-Do-you-really-understand-C-21st-International-Obfuscated-C-Code-Contest-winning-entries">IOCCC Winning Entries</a>;</li><li><a href="http://www.perlmonks.org/">PerlMonks</a>;</li><li><a href="http://www.iwriteiam.nl/SigProgC.html">C Cignature Programs</a>;</li><li><a href="https://codegolf.stackexchange.com/questions/tagged/tips?sort=votes&amp;pageSize=15">CodeGolf-StackExchange: Tips</a>, <a href="https://codegolf.stackexchange.com/questions/69/golf-you-a-quine-for-great-good">CodeGolf-StackExchange: Quine</a>, <a href="https://stackoverflow.com/questions/1995113/strangest-language-feature">StackOverflow: Strangest Language Feature</a>;</li><li><a href="http://js1k.com/">JS1K</a>;</li><li><a href="https://www.quora.com/What-is-the-most-elegant-line-of-code-youve-seen">Quora: Elegant Code</a>, <a href="https://www.quora.com/What-is-the-shortest-and-most-effective-code-ever-written">Quora: Shortest Effective Code</a>, <a href="https://www.quora.com/Whats-the-coolest-thing-you-can-get-a-computer-to-do-in-10-lines-of-code">Quora: Coolest Thing in 10 Line</a>;</li><li><a href="https://web.archive.org/web/20170319051614/http://cs.lmu.edu:80/~ray/notes/quineprograms/">QuinePrograms</a>;</li><li><a href="http://code-poetry.com/">CodePoetry</a>;</li><li><a href="http://golf.shinh.org/all.rb">Anarchy Golf</a>;</li><li><a href="http://uguu.org/sources.html">http://uguu.org/sources.html</a>;</li><li><a href="https://gist.github.com/xem/206db44adbdd09bac424">JS Code Golfing</a>.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>9 интересных трюков на Си, с которыми вы раньше не сталкивались</title>
      <link>https://tproger.ru/translations/9-clang-tricks</link>
      <comments>https://tproger.ru/translations/9-clang-tricks?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/9-clang-tricks</guid>
      <description><![CDATA[<p>Редкие приёмы Си: проверка конца файла через возвращаемое значение scanf() и вывод строки «Success» при использовании аргумента «%m» в printf().</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/9-clang-tricks">9 интересных трюков на Си, с которыми вы раньше не сталкивались</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Язык Си]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 15 Jan 2017 18:05:28 GMT</pubDate>
      <content:encoded><![CDATA[<p>В этой статье мы рассмотрим несколько редких приёмов языка Си. О некоторых из них я раньше не слышал, и вы, скорее всего, тоже. Если ваш преподаватель или коллега хвастаются знанием Си, просто задайте им пару вопросов об этих трюках, и если они справятся, то они действительно шарят 🙂</p><h3>Используем возвращаемое значение scanf() для проверки конца файла</h3><p>Очень полезно в системах с автоматической проверкой, где подача входных данных заканчвается EOF.</p><h3>"%m" как аргумент printf() выводит “Success”</h3><p>"%m" выводит “Success” только в том случае, когда errno == 0. Это сокращение для строкового представления последнего наблюдаемого состояния ошибок. Например, если функция выдаст ошибку до printf, вывод будет другим.</p><h3>Неявная инициализация целых нулём и единицей</h3><h3>Вывод чисел от 1 до 200 без использования циклов, переходов и рекурсии</h3><h3>C++ Sucks?</h3><p>Вы будете удивлены, но этот код выведет надпись “C++Sucks”, и <a href="http://stackoverflow.com/questions/17992553/concept-behind-these-four-lines-of-tricky-c-code">вот тому объяснение</a>.</p><h3>А вы сталивались с оператором “спуска” --&gt;?</h3><p>На самом деле --&gt; — это никакой не оператор, а комбинация двух операторов: -- и &gt;. Разберёмся на примере:  в условии цикла переменная x уменьшается, но возвращается старое значение x, которое сравнивается с 0 оператором &gt;.</p><p>Вывод:</p><h3>Магия scanf</h3><h3>Сложение чисел без использования оператора +</h3><p>Кстати, с другими примерами использования битовых операций можно ознакомиться <a href="https://tproger.ru/tag/bit-manipulation/">в наших статьях</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Чему я научился, написав шесть функций, которые делали одно и то же</title>
      <link>https://tproger.ru/translations/practice-makes-perfect</link>
      <comments>https://tproger.ru/translations/practice-makes-perfect?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/practice-makes-perfect</guid>
      <description><![CDATA[<p>Джексон Бейтс на конкурсе Free Code Camp искал сумму чисел, делящихся на 3 и 5, и сравнивал эффективность решений собственными тестами и бенчмарками.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/practice-makes-perfect">Чему я научился, написав шесть функций, которые делали одно и то же</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Головоломки]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Материалы от друзей Tproger]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 21 Dec 2016 19:29:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рассказывает Jackson Bates</p><p>Несколько недель назад на  <a href="http://forum.freecodecamp.com/t/javascript-algorithm-challenge-october-9-through-16/44096?u=jacksonbates">Free Code Camp’s Forum</a> дали старт неофициальному алгоритмическому соревнованию.</p><p>Задача была весьма простой: вернуть сумму всех чисел, делимых без остатка на 3 и 5, входящих в диапазон от 0 до числа N, где N — входной параметр функции.</p><p>Но вместо поиска хоть какого-нибудь решения <a href="https://medium.com/u/bf42d244c85">P1xt</a> (организатор соревнования) потребовал сфокусироваться на эффективности. Что в свою очередь подразумевает написание собственных тестов и бенчмарков для оценки производительности найденных решений.</p><p>Именно такой подход я использовал для каждой написанной мной функции. В конце я покажу самое быстрое решение, которое буквально взорвало мне мозг и которое меня кое-чему научило.<br /></p><h3>Функция №1: массив, push, прибавка</h3><p>Для решения задач, подобных этой, мои мозги привыкли делать следующее: создать массив, затем что-то сделать с массивом.</p><p>Эта функция создает массив и методом push добавляет в него числа, которые соответствуют условию (делятся на 3 и 5). Затем цикл пробегается по массиву, суммируя все его значения.</p><h3>Настройка тестов</h3><p>Далее для автоматизированных тестов этой функции я использовал Mocha и Chai, запущенных на NodeJS.</p><p>Если хотите получить больше информации по установке Mocha и Chai, то вы можете почитать об этом в соответствующем гайде на форуме <a href="http://forum.freecodecamp.com/t/testing-your-own-code-using-mocha-and-chai-simple-example/44149?u=jacksonbates">Free Code Camp</a>.</p><p>Я написал простой тест, используя значения, предоставленные организатором. Заметьте, что в коде ниже функция подключена как модуль.</p><p>Когда я запустил тест строчкой mocha testMult.js, он вернул следующее:</p><figure><img src="https://media.tproger.ru/uploads/2016/12/1-tmJwwmFxPQevv_kEKOWPRw.png" alt="" /></figure><p>Все последующие функции в этой статье прогонялись через этот же тест.</p><h3>Функция №2: массив, push, reduce</h3><p>Эта функция использует подход, похожий на предыдущий, но вместо использования цикла for для подсчета конечной суммы в ней используется более изящный метод reduce.</p><h3>Настройка бенчмарка</h3><p>Теперь, когда у нас есть две функции, мы можем сравнить их эффективность. Опять же, спасибо организатору, который предоставил соответствующий скрипт на форуме.</p><p>Если запустить скрипт строчкой node performance.js, то вы получите следующий ответ в терминале:</p><p>Итак, использование метода reduce дает нам 5-кратный прирост в скорости!</p><p>Если это не вдохновляет на поиск новых решений, то я уже не знаю, что может вдохновить!</p><h3>Функция №3: while, массив, reduce</h3><p>Поскольку я всегда полагался на цикл for, мне следовало протестировать альтернативный while цикл:</p><p>И каков результат? Чуть-чуть медленнее:</p><h3>Функция №4: while, sum, без массивов</h3><p>Итак, обнаружив, что тип цикла не дает большой выгоды, я задумался: а что, если я буду использовать метод, который вообще избегает каких-либо массивов?</p><p>Увидев результаты, я сразу понял, насколько же я был неправ, используя только массивы…</p><p>Еще одно массивное улучшение: почти в 5 раз быстрее и в 27 раз быстрее, чем мое первое решение!</p><h3>Функция №5: for, sum</h3><p>Конечно же мы уже знаем, что цикл for работает чуточку быстрее:</p><p>В данном примере используется тернарный оператор для проверки соответствия условию, но мои тесты показывают, что не-тернарный вариант — такой же по производительности.</p><p>И опять чуть-чуть быстрее.</p><p>Мое финальное решение оказалось в 28 раз быстрее, чем самое первое.</p><p>Я чувствую себя чемпионом.</p><p>Я был на седьмом небе.</p><p>Я почивал на лаврах.</p><h3>Погружаемся в математику</h3><p><br />Неделя прошла, и на форуме появились финальные решения других участников. Функция, которая оказалась быстрее всех, не использует циклы, но использует алгебраическую формулу для подсчета чисел:</p><p>Готовы узнать результат?..</p><h3>Математика быстрее всех</h3><p>Победившая функция оказалась примерно в 9 690 раз быстрее, чем мое лучшее решение и в 275 858 раз быстрее, чем моя первая имплементация.</p><p>Если я вам понадоблюсь, то можете искать меня в Khan Academy, изучающим математику.</p><p>Спасибо всем, кто принял участие в соревновании и поделился своими решениями. Дух взаимопомощи помогает всем участникам осваивать новые методы.</p><p>Если вам интересно, то <a href="https://github.com/P1xt/algo-oct-17">тут</a> P1xt описал все правила соревнования и прочие вещи.</p><p>За перевод благодарим нашего подписчика, Даниила Высоцкого</p>]]></content:encoded>
    </item>
    <item>
      <title>Хитрости с битовыми операциями</title>
      <link>https://tproger.ru/articles/awesome-bits</link>
      <comments>https://tproger.ru/articles/awesome-bits?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/awesome-bits</guid>
      <description><![CDATA[<p>Приёмы работы с битами: установка, обнуление и переключение n-го бита, округление до степени двойки, умножение и деление на 2 и проверка на равенство.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/awesome-bits">Хитрости с битовыми операциями</a>»</p>]]></description>
      <category><![CDATA[Поразрядная обработка]]></category>
      <category><![CDATA[Низкоуровневое программирование]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 21 Dec 2016 17:04:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Нашли и оформили подборку различных хитрых приёмов с битовыми операциями. С основами битовых операций также можно ознакомиться <a href="https://tproger.ru/translations/bitwise-operations/">в нашей статье</a>. Если вы знаете какие-то трюки, которые не вошли в этот список, делитесь ими в комментариях!</p><h3>Целые числа</h3><p>Установка n-ого бита</p><p>Обнуление n-ого бита</p><p>Переключение n-ого бита</p><p>Округление до следующей степени двойки</p><p>Получение максимального целого</p><p>Получение минимального целого</p><p>Получение максимального long</p><p>Умножение на 2</p><p>Деление на 2</p><p>Умножение на m-тую степень 2</p><p>Деление на m-тую степень 2</p><p>Проверка на равенство</p><p>На 35% быстрее, чем JS 🙂</p><p>Проверка на чётность</p><p>Обмен значениями</p><p>Модуль</p><p>Максимум двух чисел</p><p>Минимум двух чисел</p><p>Проверка на одинаковый знак</p><p>Смена знака</p><p>Вычисление 2^n</p><p>Проверка на степень 2</p><p>Остаток от деления 2^n на m</p><p>Среднее арифметическое</p><p>Получение m-ого бита n (справа налево)</p><p>Установка m-ого бита n (справа налево)</p><p>Проверка n-ого бита</p><p>Выделение самой правой 1</p><p>Выделение самого правого 0</p><p>Смена самого правого 0 на 1</p><p>n+1</p><p>n-1</p><p>if (x==a) x=b; if (x==b) x=a;</p><h3>Строки</h3><p>Преобразование буквы в строчную</p><p>Преобразование буквы в заглавную</p><p>Смена вида буквы</p><p>Номер буквы в алфавите</p><p>Номер заглавной буквы в алфавите</p><p>Номер строчной буквы в алфавите</p><h3>Прочее</h3><p>Быстрая смена цвета с R5G5B5 на R8G8B8</p><p>Примечание: можно использовать только латиницу.</p>]]></content:encoded>
    </item>
    <item>
      <title>Магия JavaScript: что можно сделать, используя лишь 6 символов?</title>
      <link>https://tproger.ru/translations/js-magic-with-6-symbols</link>
      <comments>https://tproger.ru/translations/js-magic-with-6-symbols?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/js-magic-with-6-symbols</guid>
      <description><![CDATA[<p>Автоматическое приведение типов в JavaScript позволяет писать бредовый, но валидный код — достаточно набора всего из шести служебных символов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/js-magic-with-6-symbols">Магия JavaScript: что можно сделать, используя лишь 6 символов?</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 06 Nov 2016 16:33:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>JavaScript — это одновременно странный и замечательный язык, который позволяет нам писать абсолютно бредовый код, являющийся валидным. Он пытается помогать нам, конвертируя величины в нужные типы в зависимости от того, как мы с ними работаем.</p><p>Если мы прибавляем строку к чему-то, результат будет конвертирован в строку.</p><p>Если мы припишем слева от чего-то плюс или минус, будет произведена попытка конвертации строки в число.</p><p>Если на что-то навесить логическое отрицание, результат будет представлен как логическая величина.</p><p>Мы можем использовать это и творить магию, используя лишь эти символы: [, ], (, ), ! и +. Если вы читаете статью не с мобильного устройства, то вы можете открыть консоль в браузере и выполнять весь код там.</p><p>Начнём с основ. То, что стоит запомнить:</p><ol><li>Префикс ! конвертирует в Boolean;</li><li>Префикс + конвертирует в число;</li><li>Сложение с [] конвертирует в строку.</li></ol><p>Вот пример:</p><p>Кроме того, нужно знать, что символы из строки можно получать следующим образом:</p><p>Также запомните, что числа можно получать сложением других чисел в строковом виде и конвертацией результата в числовой формат:</p><p>Так, а теперь попробуем использовать рассмотренные свойства и получить букву a.</p><p>Забавно!</p><p>Таким образом, путём нехитрых махинаций мы можем получить все буквы из слов true и false. a, e, f, l, r, s, t, u. Хорошо, а можем ли мы взять буквы ещё где-то?</p><p>Ну, ещё есть undefined, который и можно получить, сделав что-то глупое, как [][[]]. Конвертация в строку даст нам буквы d, i и n.</p><p>Используя все эти буквы, можно составить слова fill, filter и find. Конечно, есть и другие доступные слова, но ценностью именно этих слов является то, что они — <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Mutator_methods">методы массивов</a>. Это означает, что они являются частью объекта Array и их можно вызывать прямо для массивов-сущностей. Например, [2,1].sort().</p><p>Кроме того, нужно помнить, что свойства объекта в JS можно использовать <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors">как через точку, так и через квадратные скобки</a>. Поскольку методы массива — это свойства объекта Array, мы можем вызывать их, используя скобки вместо точки.</p><p>То есть [2,1]["sort"]() — это то же самое, что и [2,1].sort().</p><p>Давайте посмотрим, что произойдёт, когда мы попробуем использовать один из доступных нам методов, не вызывая его.</p><p>Это выдаст function fill() { [native code] }. Конвертируем заголовок метода в строку:</p><p>И получим новые символы: c, o, v, (, ), {, [, ], },  .</p><p>Получив буквы c и o, можем составить слово constructor. constructor — это метод, который есть у всех JS-объектов, и он возвращает их функцию-конструктор.</p><p>Получим строковое представление всех конструкторов наших объектов:</p><p>Из этих строк мы можем пополнить наш арсенал следующими символами: B, N, S, A, m, g, y.</p><p>Теперь мы можем составить "toString", функцию, которую можно использовать с квадратными скобками. Только на этот раз мы вызовем её.</p><p>Но мы же уже можем конвертировать в строку всё что угодно, так как нам это поможет?</p><p>Что, если я скажу вам, что метод toString типа Number обладает <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString">секретным аргументом</a> radix, который меняет <a href="https://en.wikipedia.org/wiki/Radix">основание</a> возвращаемого числа перед конвертацией в строку. Смотрите:</p><p>Но зачем останавливаться на 16? Максимум — это 36, чего хватает на все символы 0–9 и a–z. Теперь мы можем получить любую цифру или букву:</p><p>Отлично! Но как же пунктуационные символы и заглавные буквы? Идём дальше!</p><p>В зависимости от того, где вы исполняете свой JS-код, он может получать, а может и не получать доступ к заранее определённым объектам и данным. Есть вероятность, что при запуске в браузере вы сможете получить доступ к обёрточным методам HTML.</p><p>Например, bold — это метод String, оборачивающий строку в тег &lt;b&gt;.</p><p>Это даст нам символы &lt;, &gt; и /.</p><p>Возможно, вы слышали о функции escape. По сути, она конвертирует строку в URI-формат, который могут распознать браузеры. Если мы передадим ей пробел, то получим %20. Передадим &lt; — получим %3C. Эта заглавная C очень важна для получения остальных символов.</p><p>Благодаря ей мы можем использовать функцию fromCharCode, возвращающую символ Юникода по данному десятичному представлению. Она является частью объекта String, который можно получить, вызвав конструктор любой строки.w</p><p>Для получения десятичных представлений символов можно использовать сайт <a href="http://unicodelookup.com/">Unicode lookup</a>.</p><p>Хорошо, теперь мы можем написать что угодно в виде строки и выполнить любую функцию, которая принадлежит типам Array, String, Number, Boolean или Object, через их конструкторы. Немало для 6 символов. Но это не конец.</p><p>Чем является конструктор любой функции?</p><p>Ответ: function Function() { [native code] }, настоящий объект Function.</p><p>Используя его, мы можем передать строку кода, чтобы создать реальную функцию.</p><p>Получим:</p><p>Что можно вызвать сразу же, просто добавив в конце (). Да, теперь мы можем исполнять строки кода!</p><p>ФУХ. Вот теперь всё!</p><p>Мы можем получить доступ к любому символу, объединять их в валидный код и исполнять его. Это значит, что JS является <a href="https://en.wikipedia.org/wiki/Turing_completeness">полным по Тьюрингу</a> языком из 6 символов [, ], (, ), + и !.</p><p>Не верите? Запустите это в консоли:</p><p>Если вы читаете статью с мобильного устройства, код выше — это исполняемая функция alert("wtf").</p><p><a href="http://www.jsfuck.com/">Вот инструмент</a>, который может автоматизировать конверсию, а <a href="https://raw.githubusercontent.com/aemkei/jsfuck/master/jsfuck.js">вот так</a> он переводит каждый символ.</p><h3>Ну и как это может пригодиться?</h3><p>Никак 🙂 eBay недавно <a href="http://arstechnica.co.uk/security/2016/02/ebay-has-no-plans-to-fix-severe-bug-that-allows-malware-distribution/">нахимичил</a> что-то в коде, и продавцы смогли встраивать исполняемый JS в свои страницы, используя только эти символы, но такие атаки очень редки. Можно подумать про обфускацию, но, будем честны, есть методы получше.</p><p>Спасибо за внимание!</p>]]></content:encoded>
    </item>
    <item>
      <title>На GitHub выложили тетрис, целиком помещающийся в загрузочном секторе</title>
      <link>https://tproger.ru/news/tetros-on-mbr</link>
      <comments>https://tproger.ru/news/tetros-on-mbr?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Лапа]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/tetros-on-mbr</guid>
      <description><![CDATA[<p>Клон Tetris занимает 446 байт и умещается в 512-байтном загрузочном секторе MBR, поэтому запускается сам, без всякой операционной системы.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/tetros-on-mbr">На GitHub выложили тетрис, целиком помещающийся в загрузочном секторе</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Язык ассемблера]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 05 Oct 2016 18:31:52 GMT</pubDate>
      <content:encoded><![CDATA[<p><a href="https://github.com/daniel-e/tetros">TetrOS</a> — клон знаменитого Tetris, написанный на ассемблере. Он целиком вмещается в 512 байт загрузочного сектора (ему требуется всего 446 байт места, это как раз максимальный размер загрузчика в <a href="https://ru.wikipedia.org/wiki/%D0%93%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D1%87%D0%BD%D0%B0%D1%8F_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C">MBR</a>).</p><p>MBR — раздел, содержащий код и данные, необходимые для последующей загрузки операционной системы и расположенные в первых физических секторах. Самые первые 446 байт диска отдаются под код загрузчика. Именно в это место и записывается TetrOS.</p><p>Естественно, из-за таких свойств он загружается перед любой операционной системой — никакой ОС ему не требуется, он работает сам. Да-да, вы не ослышались, TetrOS — сам себе загрузчик.</p><p>Вот так это выглядит на экране:</p><p>А исходник на загрузочном секторе выглядит так:</p><figure><img src="https://media.tproger.ru/uploads/2016/10/code.png" alt="" /></figure><p>И да, это весь исходник. Вы же помните, что он весит всего 446 байт?</p><p>Можно запустить эту «чудо-операционную систему» под qemu или даже по-настоящему установить на загрузочный раздел диска или флешки.</p><h3>Запуск</h3><p>qemu</p><p>Просто установите qemu:</p><p>sudo apt-get install qemu</p><p>и запустите:</p><p>make run</p><h3>Загрузка на флешку</h3><p>Скопируйте образ на флешку. Допустим, если флешка подмонтирована как /dev/sde, вам понадобится выполнить следующую команду, чтобы записать на ее загрузочный сектор TetrOS:</p><p>sudo dd if=tetros.img of=/dev/sde</p><h3>Описание игры</h3><p>Разработчик сумел всего в 512 байт памяти впихнуть не самый скучный дизайн. У каждого кирпичика в игре есть свой цвет, управление производится кнопками, в случае поражения игра завершается, кирпичики генерируются случайным образом… BolgenOS и рядом не стояла!</p><p>К несчастью, из-за размера от некоторых фич пришлось отказаться. В игре нет подсчета очков, рестарта игры без перезагрузки и отображения того, каким будет следующий кирпичик.</p><p>Игра написана на nasm, и ее можно собрать самостоятельно. Устанавливаем nasm:</p><p>sudo apt-get install nasm</p><p>Собираем с помощью команды make. На выходе вы получите файл tetros.img.</p><h3>Аналоги</h3><p>Это не единственный проект, умещающий какую-либо классическую игру в один загрузочный сектор. Вот, например:</p><ul><li><a href="https://github.com/dbittman/bootris">Bootris</a></li><li><a href="https://github.com/Shikhin/tetranglix">Tetranglix</a></li><li><a href="http://olivier.poudade.free.fr/src/BootChess.asm">BootChess</a></li><li><a href="https://github.com/programble/tetrasm">Tetrasm</a></li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Объясните, что делает код ((n &amp; (n - 1)) == 0)</title>
      <link>https://tproger.ru/problems/explaination-what-the-following-code-do</link>
      <comments>https://tproger.ru/problems/explaination-what-the-following-code-do?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/problems/explaination-what-the-following-code-do</guid>
      <description><![CDATA[<p>Проверка n &amp; (n - 1) == 0 означает, что у чисел n и n - 1 нет общих единичных битов. Разбор строится на ручном вычитании единицы в двоичной записи.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/problems/explaination-what-the-following-code-do">Объясните, что делает код ((n &amp; (n - 1)) == 0)</a>»</p>]]></description>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Задачки]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 30 Jan 2015 09:59:32 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вернемся к «истокам».</p><p>Что означает A &amp; B == 0?</p><p>Это означает, что А и B не содержат на одних и тех же позициях единичных битов. Если n &amp; (n - 1) == 0, то n и n - 1 не имеют общих единиц.</p><p>На что похоже n - 1 (по сравнению с n)?</p><p>Попытайтесь проделать вычитание вручную (в двоичной или десятично системах).</p><p>Что произойдет?</p><p>Когда вы отнимаете единицу, посмотрите на младший бит. 1 вы замените на 0. Но если там стоит 0, то вы должны заимствовать из старшего бита. Вы изменяете каждый бит с 0 на 1, пока не дойдете до 1. Затем вы инвертируете единицу в ноль, — все готово.</p><p>Таким образом, можно сказать, что n - 1 будет совпадать с n в каких-то битах, за исключением того, что младшим нулям в n соответствуют единицы в n - 1, а последний единичный бит в n становится нулем в n - 1.</p><p>Что значит n &amp; (n - 1) == 0?</p><p>n и n - 1 не содержат общих единиц. Предположим, они имеют вид:</p><ul><li>n = abcde1000</li><li>n - 1 = abcde0111</li></ul><p>abcde должны быть нулевыми битами, то есть n имеет вид 000001000. Таким образом, значение n – степень двойки.</p><p>Итак, наш ответ: логическое выражение ((n &amp; (n-1)) == 0) истинно, если n является степенью двойки или равно нулю.</p><p>Разбор взят из книги Гейл Л. Макдауэлл «Cracking the Coding Interview» (есть в переводе).</p>]]></content:encoded>
    </item>
  </channel>
</rss>