<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/rss/rss-styles.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>azer.one</title>
    <description>appsec engineer &amp; full-stack developer | ai enthusiast</description>
    <link>https://azer.one/</link>
    <language>en</language>
    <managingEditor>azer.one</managingEditor>
    <webMaster>azer.one</webMaster>
    <author>azer.one</author>
    <pubDate>2026-01-30T12:41:47.819Z</pubDate>
    <lastBuildDate>2026-01-30T12:41:47.819Z</lastBuildDate>
    <generator>azer.one</generator>
    <atom:link href="https://azer.one//rss.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>😨 Что случилось с Faker.js? Темная сторона Open Source</title>
      <link>https://azer.one//posts/old-posts/faker-js</link>
      <guid>https://azer.one//posts/old-posts/faker-js</guid>
      <updated>2022-01-09T00:00:00.000Z</updated>
      <pubDate>2022-01-09T00:00:00.000Z</pubDate>
      <description><![CDATA[История о том, как разработчик популярной JavaScript-библиотеки Faker.js удалил свой код в знак протеста против эксплуатации Open Source труда крупными корпорациями.]]></description>
      <content:encoded><![CDATA[<img src="https://azer.one/_astro/aron-swartz.CE9UAuLB_2gl7xJ.webp" alt="😨 Что случилось с Faker.js? Темная сторона Open Source" style="width: 100%; height: auto; margin-bottom: 1em;" />
<h2>🤔 Что случилось?</h2>
<p>4-го января 2022-го года разработчик популярной NPM-библиотеки с открытым исходным кодом <a href="https://www.npmjs.com/package/faker" rel="noopener noreferrer" target="_blank">Faker.js</a> внезапно <strong>удалил исходный код с</strong> <a href="https://github.com/Marak/faker.js" rel="noopener noreferrer" target="_blank"><strong>GitHub</strong></a> <strong>и</strong> <a href="https://www.npmjs.com/package/faker" rel="noopener noreferrer" target="_blank"><strong>NPM</strong></a>. Версия пакета обновилась до <strong>6.6.6</strong>, а в README было написано: <strong>“Что на самом деле случилось с Аароном Шварцем?”</strong></p>
<img src="./faker-js-gh-repo.jpg" alt="GitHub репозиторий Faker.js" />
<p>Недельное количество установок <strong>Faker.JS</strong> <strong>(более 2.5 миллионов)</strong> <strong>превышает</strong> количество установок <strong>Vue.JS (более 2.3 миллионов)</strong></p>
<p>7-го января разработчик Faker.JS <a href="https://twitter.com/marak/status/1479200803948830724" rel="noopener noreferrer" target="_blank">сообщил в Twitter-е</a>, что NPM <strong>без его ведома восстановила</strong> все предыдущие версии Faker.JS, а GitHub и вовсе <strong>заблокировал его аккаунт</strong>. Он потерял доступ <strong>к более 100 приватным репозиториям</strong>.</p>
<img src="./twitter-post-marak.jpg" alt="«NPM вернул предыдущие версии faker.js, а Github ограничил мой доступ ко всем публичным и приватным проектам. У меня сотни проектов.»" />
<h2>😓 Кто такой Аарон Шварц?</h2>
<img src="./aron-swartz.png" alt="Борец за свободу слова в интернете Аарон Шварц" />
<p><strong>Аарон Шварц</strong> — <strong>легендарный</strong> программист, создавший <strong>RSS</strong>, <strong>Markdown</strong>, авторское право <strong>Creative Commons</strong>, а также платформу, позже взятую за основу социальной сети <strong>Reddit</strong>.</p>
<blockquote><p><strong>«Информация — это власть.</strong> Но, как случается со всякой властью, есть те, кто хочет, чтобы она была только у них. Горстка частных корпораций все активнее оцифровывает мировое научное и культурное наследие, на протяжении веков публиковавшееся в книгах и журналах, чтобы его спрятать ото всех, — писал Шварц. — Они говорят о воровстве, пиратстве, как будто обмен знаниями может быть моральным эквивалентом ограбленного судна с убитым экипажем. Делиться не аморально — напротив, это моральный императив (…). <strong>Берите информацию, где бы она ни хранилась, копируйте и распространяйте.</strong> Берите документы без авторских прав и добавляйте в архивы. Покупайте секретные базы и публикуйте в интернете. Скачивайте научные журналы и публикуйте их на файлообменниках»</p></blockquote>
<p>Последние полтора года Аарон Шварц находился в тюрьме <a href="http://habrahabr.ru/post/124562/" rel="noopener noreferrer" target="_blank">за нелегальное скачивание более 4 млн документов из базы данных JSTOR</a> — архива академических журналов и научных работ. Хотя <a href="http://www.jstor.org/" rel="noopener noreferrer" target="_blank">JSTOR</a> — некоммерческая цифровая библиотека, и документы доступны бесплатно в онлайне, но некоторые клиенты платят по 10 центов за документ, если пользуются специальным интерфейсом.</p>
<img src="./aron-swartz-2.png" alt="Аарон Шварц в подсобке Массачусетского технологического института, во время &quot;преступления&quot;" />
<p>JSTOR отказалась от претензий к Шварцу, но <strong>прокуратура приняла решение продолжить дело.</strong> В сентябре 2012-го ему грозило <strong>50 лет тюремного заключения</strong>, но в январе 2013-го года он совершил самоубийство.</p>
<p>Что же на самом деле случилось с Аароном — отдельная тема для обсуждений. Основатель <a href="https://twitter.com/marak/status/1478540823180582914" rel="noopener noreferrer" target="_blank">опубликовал</a> в своём Twitter фрагмент из обсуждения этой темы в <a href="https://www.reddit.com/r/conspiracy/comments/r92k18/the_fact_that_ghislaine_fucking_maxwell_was_a/" rel="noopener noreferrer" target="_blank">Reddit</a>.</p>
<h2>🤕 Темная сторона Open Source</h2>
<p>Автор Faker.JS, <strong>удалив одну из самых востребованных JavaScript-библиотек</strong>, напомнил миру о проблеме разработчиков открытого исходного кода, где крупные коммерческие корпорации (например, практически все из списка Fortune500) <strong>используют Open Source труд, не возвращая ничего взамен.</strong> И в результате получается, что многие разработчики <strong>работают за спасибо</strong> или под грузом ответственности за свой более ранний труд.</p>
<p>Каждый будет делать свои выводы из этой истории, которая ещё не закончилась. Поделитесь этой новостью, чтобы больше людей знало <strong>тёмную сторону Open Source</strong>.</p>]]></content:encoded>
      <author>Azer Sadykhzadeh</author>
      <category>opensource</category><category>oldposts</category>
    </item>
    <item>
      <title>Задача о максимальном произведении трех чисел массива</title>
      <link>https://azer.one//posts/old-posts/max-product-of-3-integers</link>
      <guid>https://azer.one//posts/old-posts/max-product-of-3-integers</guid>
      <updated>2019-05-21T00:00:00.000Z</updated>
      <pubDate>2019-05-21T00:00:00.000Z</pubDate>
      <description><![CDATA[Разбор алгоритмической задачи из собеседования в Apple - поиск максимального произведения трех чисел в массиве с оптимальной сложностью O(n).]]></description>
      <content:encoded><![CDATA[
<p>Задача, которую предлагали на собеседованиях в <strong>Apple</strong>: у вас есть массив с целыми числами, в том числе и отрицательными, вам нужно найти самое большое произведение 3 чисел из этого массива.</p>
<p>К примеру, у вас есть массив <code>list_of_ints</code>, содержащий числа <code>{-10, -10, 1, 3, 2}</code>. Функция, которая обрабатывает этот массив, должна вернуть <strong>300</strong>, так как <code>(-10) * (-10) * 3 = 300</code>. Задание нужно выполнить максимально эффективно, не забывая про отрицательные числа.</p>
<h2>Алгоритм решения</h2>
<p>Методов решения много, но не так просто добиться <strong>O(n)</strong> времени выполнения и <strong>O(1)</strong> затрат памяти. Для эффективного решения задачи мы создадим и будем наблюдать за состоянием следующих переменных:</p>
<ul>
<li><code>highest_product_of_three</code></li>
<li><code>highest_product_of_2</code></li>
<li><code>highest</code></li>
<li><code>lowest_product_of_2</code></li>
<li><code>lowest</code></li>
</ul>
<p>Когда мы пройдемся по массиву до конца, в <code>highest_product_of_three</code> будет содержаться наш ответ, а остальные переменные мы используем как временный буфер. <code>highest_product_of_2</code> и <code>lowest_product_of_2</code> будут содержать наибольшее произведение из двух и наименьшее произведение из двух соответственно, а проходя по массиву, мы будем проверять произведение текущего числа <code>current</code> с этими переменными (отрицательный <code>current</code> с <code>lowest_product_of_2</code> и положительный с <code>highest_product_of_2</code>). <code>highest</code> и <code>lowest</code> нам нужны для запоминания минимального и максимального чисел в массиве.</p>
<h2>Реализация</h2>
<p>Специально для вас, реализация описанных выше действий на Python:</p>
<pre><code>def highest_product_of_3(list_of_ints):
    # Проверим, чтобы в массиве было 3 и больше чисел.
    if len(list_of_ints) &lt; 3:
        raise Exception('Less than 3 items!')

    # Мы начнем с 3-его элемента массива (с индекса 2),
    # так как первые 2 элемента уже сразу пойдут
    # в highest_product_of_2 и lowest_product_of_2.
    highest = max(list_of_ints[0], list_of_ints[1])
    lowest =  min(list_of_ints[0], list_of_ints[1])
    highest_product_of_2 = list_of_ints[0] * list_of_ints[1]
    lowest_product_of_2  = list_of_ints[0] * list_of_ints[1]

    # Также вычислим highest_product_of_three из первых 3-х элементов.
    highest_product_of_three = list_of_ints[0] * list_of_ints[1] * list_of_ints[2]

    # Начинаем проход по массиву с индекса 2.
    for current in list_of_ints[2:]:

        # проверяем возможность увеличить highest_product_of_three
        # или оставляем его как есть.
        highest_product_of_three = max(
            highest_product_of_three,
            current * highest_product_of_2,
            current * lowest_product_of_2)

        # То же самое проверим и на максимальном произведении из двух.
        highest_product_of_2 = max(
            highest_product_of_2,
            current * highest,
            current * lowest)

        # И на минимальном произведении из двух.
        lowest_product_of_2 = min(
            lowest_product_of_2,
            current * highest,
            current * lowest)

        # Появилось ли новое максимальное число?
        highest = max(highest, current)

        # Появилось ли новое минимальное число?
        lowest = min(lowest, current)

    return highest_product_of_three
</code></pre>
<h2>Сложность алгоритма</h2>
<p>Производительность</p><p>Сложность алгоритма — <strong>O(n)</strong> по времени выполнения и <strong>O(1)</strong> по памяти.</p>
<p><strong>Спасибо за внимание!</strong></p>
<hr />
<p><strong>Источник</strong>: <a href="https://www.interviewcake.com/" rel="noopener noreferrer" target="_blank">InterviewCake</a></p>]]></content:encoded>
      <author>Azer Sadykhzadeh</author>
      <category>algorithm</category><category>oldposts</category><category>python</category>
    </item>
    <item>
      <title>По стопам Эвклида или 8 способов нахождения наибольшего общего делителя</title>
      <link>https://azer.one//posts/old-posts/gcd</link>
      <guid>https://azer.one//posts/old-posts/gcd</guid>
      <updated>2019-05-04T00:00:00.000Z</updated>
      <pubDate>2019-05-04T00:00:00.000Z</pubDate>
      <description><![CDATA[Подробный разбор восьми различных алгоритмов для вычисления НОД - от наивных до оптимизированных, с анализом производительности и примерами кода.]]></description>
      <content:encoded><![CDATA[<img src="https://azer.one/_astro/baby-with-glasses.CP_KARaJ_ZjQh9g.webp" alt="По стопам Эвклида или 8 способов нахождения наибольшего общего делителя" style="width: 100%; height: auto; margin-bottom: 1em;" />
<p><img src="./baby-with-glasses.jpg" alt="baby-with-glasses" />
<em>фотка не моя :)</em></p>
<h2>Мини-история этой статьи</h2>
<p>Готовился я к финалу Республиканской Олимпиады по информатике (среди школьников): повторял ужасно много тем, такие как графы, динамическое программирование (ДП), теория чисел…</p>
<p>Решал все задачи, которые только попадались мне, не обращая внимания на уровень сложности: и простые, и сложные. Натыкался и на задачи формата: “Даны числа A и B. Напишите программу, которая выводит на экран НОД(A,B)”.</p>
<p>Задача простая, решил её тогда одной строчкой.</p>
<p>В один такой прекрасный день участник одной телеграм-группы по программированию попросил меня найти ему какие-нибудь простенькие задачки утверждает, что “начал он заниматься кодингом совсем недавно”. Я отправил ему 10-15 задач среднего уровня, одной из которых была та самая: задача про наибольший общий делитель.</p>
<p>Проходит время, он мне пишет, что задачи и вправду интересные, вот только не может решить он почему-то лишь одну задачу. “Я отправляю решение, но только из 30 тестов проходит только 25. На остальные тесты идет превышение по времени.”</p>
<p>Попросил я его скинуть мне свой код, который даёт ему такую ошибку. Вот он:</p>
<pre><code>#include &lt;iostream&gt;
using namespace std;
int main() {
    long long a, b;
    cin &gt;&gt; a &gt;&gt; b;
    for (long long i = a; i &gt;= 1; i--) {
        if (a % i == 0 &amp;&amp; b % i == 0) {
            cout &lt;&lt; i &lt;&lt; endl;
            return 0;
        }
    }
    cout &lt;&lt; 1 &lt;&lt; endl;
    return 0;
}
</code></pre>
<p>Что ж, неудивительно, что последние пять тестов не проходит. Ведь там же большие числа, а узнать их НОД линейным путём, как написано в коде выше, не совсем уж и рационально.</p>
<p>И тут я подумал, а сколько всего существует такого рода способов? Решил погрузиться в эту тему и остановиться на 8-ми случаях: от самых “наивных” до быстрых и интересных.</p>
<h2>Прежде, чем начать…</h2>
<ol>
<li>Будем писать код НОД в виде функции.</li>
<li>Не будет использовать int. Будем использовать long long, ибо использовать в таком случае 10^9, когда есть 10^18 немного…</li>
</ol>
<p>Функции будем называть <code>long long gcd_variant_[номер_нашего_способа](long long a, long long b)</code>. Имя функции gcd от англ. Greatest Common Divisor — НОД.</p>
<p>Прочитав некоторые статьи про НОД, понял, что в коде я не стоит использовать библиотечные функции, чтобы максимальный объём кода был контролируемым. Хотя я был бы не против использовать min() и max(), но так как мы будем измерить время работы алгоритмов, лучше будем писать их вручную.</p>
<h3>Вариант 1. Перебираем от произвольного числа</h3>
<pre><code>long long gcd_variant_1(long long a, long long b) {
    for (long long i = a; i &gt;= 1; i--) {
        if (a % i == 0 &amp;&amp; b % i == 0) {
            return i;
        }
    }
    return 1;
}
</code></pre>
<p>Идея вышепоказанного алгоритма очень проста: гоним переменную цикла от первого числа до 1. Если оба числа делятся на переменную цикла без остатка, значит переменная цикла и равна НОД, а это означает, цикл можно завершить досрочно. Если цикл прошёл до конца, значит для этих чисел НОД равен 1.</p>
<p>На первый взгляд недостатков у этого кода нет. Однако, как нам известно, НОД двух чисел всегда бывает меньше этих самых чисел. Что будет если я сначала введу большее число, а затем - меньшее? Правильно, мы будем терять драгоценное для нас время! Поэтому начинать цикл от большего числа не имеет смысла.</p>
<h3>Вариант 2. Перебираем от минимального числа</h3>
<p>Как я писал выше, нам не время сейчас использовать библиотечные функции. Поэтому пишем эту функцию сами:</p>
<pre><code>long long min_function(long long a, long long b) {
    if (a &gt; b) return b;
    return a;
}

long long gcd_variant_2(long long a, long long b) {
    for (long long i = min_function(a, b); i &gt;= 1; i--) {
        if (a % i == 0 &amp;&amp; b % i == 0) {
            return i;
        }
    }
    return 1;
}
</code></pre>
<p>Вот, отличается 2-ой вариант от 1-го тем, что мы добавили простейшую функцию для вычисления минимального числа для пары чисел и инициализируем переменную цикла меньшим из двух чисел. В половине случаев такая оптимизация работать не будет (а именно тогда, когда первый аргумент и так меньше второго), однако в другой половине случаев выигрыш во времени может быть весьма значительным.</p>
<h3>Вариант 3. Пишем алгоритм с разложением на делители</h3>
<p>1-ый и 2-ой варианты мы писали перебором. Неужели мы не способны на большее?</p>
<p>В школе нам говорят, что НОД можно найти, разложив числа на простые множители:</p>
<pre><code>a = p₁^α₁ × p₂^α₂ × p₃^α₃ × ... где pᵢ - простые числа
</code></pre>
<p>А НОД будет равен произведению простых множителей, общих для обоих чисел. К примеру:</p>
<pre><code>A = 2³ × 3² × 5¹
B = 2² × 3¹ × 7¹
</code></pre>
<p>следовательно, НОД(A,B) = 2² × 3¹ = 12</p>
<p>Можем ли мы всё это реализовать в коде? Конечно!</p>
<pre><code>long long gcd_variant_3(long long a, long long b) {
    long long result = 1;

    for (long long i = 2; i &lt;= min_function(a, b); i++) {
        while (a % i == 0 &amp;&amp; b % i == 0) {
            result *= i;
            a /= i;
            b /= i;
        }
    }

    return result;
}
</code></pre>
<p>Ну неплохо! Но кажется, что со скоростью этой программы хватает желать лучшего. Интересно, а что говорит на этот счёт Google? (О, а есть Википедия!)</p>
<p>Мм, там описано нахождение НОД через каноническое разложение на простые множители, которое мы уже реализовали. Так стоп! Мы нашли ещё один способ.</p>
<h3>Вариант 4. Пишем Алгоритм Евклида (рекурсивный)</h3>
<p>В самом простом случае алгоритм Евклида применяется к паре положительных целых чисел и формирует новую пару, которая состоит из меньшего числа и разницы между большим и меньшим числом. Процесс повторяется, пока числа не станут равными. Найденное число и есть наибольший общий делитель исходной пары.</p>
<p>Ну что ж, давайте напишем пока рекурсивный метод:</p>
<pre><code>long long gcd_variant_4(long long a, long long b) {
    if (b == 0) return a;
    return gcd_variant_4(b, a % b);
}
</code></pre>
<p>Считается, что такого рода алгоритмы (рекурсивные) менее эффективны, чем итерационные, за счёт накладных расходов на вызов функции. Для проверки делаем и итерационный вариант:</p>
<h3>Вариант 5. Пишем Алгоритм Евклида (итерационный)</h3>
<pre><code>long long gcd_variant_5(long long a, long long b) {
    while (b != 0) {
        long long temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
</code></pre>
<p>Кстати, в Викиучебнике есть и другие реализации алгоритма Евклида. Кому интересно, может перейти по ссылке.</p>
<h3>Вариант 6. Пишем Бинарный алгоритм (рекурсивный)</h3>
<p>Нашел я также в просторах Интернета (вернее, опять в Википедии) такое понятие, как Бинарный алгоритм Евклида.</p>
<p>Правила:</p>
<ul>
<li>НОД(0, n) = n; НОД(m, 0) = m; НОД(m, n) = НОД(n, m)</li>
<li>НОД(1, n) = 1</li>
<li>если m и n чётные то НОД(m, n) = 2×НОД(m/2, n/2)</li>
<li>если m чётное n нечётное то НОД(m, n) = НОД(m/2, n)</li>
<li>если m нечётное n чётное то НОД(m, n) = НОД(m, n/2)</li>
<li>если m и n нечётные и m &gt; n то НОД(m, n) = НОД((m-n)/2, n)</li>
<li>если m и n нечётные и m &lt; n то НОД(m, n) = НОД(m, (n-m)/2)</li>
</ul>
<p>Напишем в первую очередь рекурсивную версию:</p>
<pre><code>long long gcd_variant_6(long long a, long long b) {
    if (a == 0) return b;
    if (b == 0) return a;
    if (a == 1 || b == 1) return 1;

    if (a % 2 == 0 &amp;&amp; b % 2 == 0) {
        return 2 * gcd_variant_6(a/2, b/2);
    }

    if (a % 2 == 0 &amp;&amp; b % 2 == 1) {
        return gcd_variant_6(a/2, b);
    }

    if (a % 2 == 1 &amp;&amp; b % 2 == 0) {
        return gcd_variant_6(a, b/2);
    }

    if (a &gt; b) {
        return gcd_variant_6((a-b)/2, b);
    } else {
        return gcd_variant_6(a, (b-a)/2);
    }
}
</code></pre>
<p>Но рекурсивные функции менее эффективны, чем итерационные…</p>
<h3>Вариант 7. Пишем Бинарный алгоритм (итерационный)</h3>
<p>Итерационная версия:</p>
<pre><code>long long gcd_variant_7(long long a, long long b) {
    long long shift = 0;

    if (a == 0) return b;
    if (b == 0) return a;

    while (((a | b) &amp; 1) == 0) {
        shift++;
        a &gt;&gt;= 1;
        b &gt;&gt;= 1;
    }

    while ((a &amp; 1) == 0) a &gt;&gt;= 1;

    do {
        while ((b &amp; 1) == 0) b &gt;&gt;= 1;

        if (a &gt; b) {
            long long temp = a;
            a = b;
            b = temp;
        }
        b = b - a;
    } while (b != 0);

    return a &lt;&lt; shift;
}
</code></pre>
<p>В добавок оставлю ссылку на эту тему в Викиучебнике, ибо там есть другие реализации бинарного алгоритма Евклида.</p>
<h3>Вариант 8. Пишем Бинарный алгоритм (итерационный), но используя битовые операции</h3>
<p>Так как отличительной особенностью бинарного алгоритма является возможность использования битовых сдвигов вместо медленных операций деления и умножения на 2, заменены арифметическими сдвигами, а проверка на чётность - на проверку младшего бита числа.</p>
<p>Эта версия функции по логике полностью совпадает с предыдущей, но операции деления и умножения на 2 заменены арифметическими сдвигами, а проверка на чётность - на проверку младшего бита числа.</p>
<pre><code>long long gcd_variant_8(long long a, long long b) {
    long long shift = 0;

    if (a == 0) return b;
    if (b == 0) return a;

    while (((a | b) &amp; 1) == 0) {
        shift++;
        a &gt;&gt;= 1;
        b &gt;&gt;= 1;
    }

    while ((a &amp; 1) == 0) a &gt;&gt;= 1;

    do {
        while ((b &amp; 1) == 0) b &gt;&gt;= 1;

        if (a &gt; b) {
            long long temp = a;
            a = b;
            b = temp;
        }
        b = b - a;
    } while (b != 0);

    return a &lt;&lt; shift;
}
</code></pre>
<h2>Ну… А что насчёт скорости?</h2>
<p>Компилировал на CodeBlocks под 64 битной Windows.</p>
<p>Среднее время для 500 пар случайных чисел:</p>
<ol>
<li>перебор от произвольного числа: 0.4835 сек</li>
<li>перебор от минимального числа: 0.486 сек</li>
<li>с разложением на делители: 0.0062 сек</li>
<li>алгоритм Евклида рекурсивный: 0.0007 сек</li>
<li>алгоритм Евклида итерационный: 0.0009 сек</li>
<li>бинарный алгоритм рекурсивный: 0.0006 сек</li>
<li>бинарный алгоритм итерационный: 0.0003 сек</li>
<li>бинарный алгоритм итерац. со сдвигом: 0.0002 сек</li>
</ol>
<p>Как и ожидалось первый алгоритм (который писал мой товарищ) катастрофически неэффективен и неудивительно, что тогда последние 5 тестов не прошли.</p>
<h2>Выводы</h2>
<ul>
<li>Первый пришедший на ум алгоритм решения какой-то задачи часто не будет оптимален. Хотя и может правильно и достаточно приемлемо работать в определённых условиях.</li>
<li>Учите математику! Обещаю, Вы не пожалеете.</li>
<li>Всегда надо попробовать подумать над улучшением алгоритма (или над альтернативным вариантом).</li>
<li>Не придумывайте велосипед! Посмотрите что сделали люди до вас.</li>
<li>Оптимизируйте код!</li>
</ul>
<h2>Ах да, спортивное программирование…</h2>
<p>Внимательные сейчас спросят: “А вот выше ты писал, что решил задачу одной строчкой?”</p>
<p>Дело в том, что программирование у меня олимпиадное, а это означает, что мне надо комбинировать такие вещи, как быстрота и лаконичность. Конечно, очень быстро никак не получится, но скорости хватает.</p>
<p>А использую я обычную функцию STL __gcd. А вот и моё решение:</p>
<pre><code>#include &lt;bits/stdc++.h&gt;
using namespace std;

int main() {
    long long a, b;
    cin &gt;&gt; a &gt;&gt; b;
    cout &lt;&lt; __gcd(a, b) &lt;&lt; endl;
    return 0;
}
</code></pre>
<p>Спасибо огромное за то, что уделили время прочтению этой статьи. До новых встреч!</p>]]></content:encoded>
      <author>Azer Sadykhzadeh</author>
      <category>algorithm</category><category>cpp</category><category>oldposts</category>
    </item>
  </channel>
</rss>