Какая самая смешная пессимизация, которую вы видели?

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

Ответ 1

В старом проекте мы унаследовали некоторых (в противном случае отличных) программистов встраиваемых систем, которые имели массовый опыт Z-8000.

Наша новая среда была 32-разрядной Sparc Solaris.

Один из парней пошел и изменил все ints на шорты, чтобы ускорить наш код, поскольку захват 16 бит из RAM был быстрее, чем захват 32 бит.

Мне пришлось написать демо-программу, чтобы показать, что захват 32-битных значений в 32-битной системе был быстрее, чем захват 16-битных значений, и объяснил, что для захвата 16-битного значения CPU должен был сделать 32 -битный широкий доступ к памяти, а затем маскировать или сдвигать биты, которые не нужны для 16-разрядного значения.

Ответ 2

Я думаю, что фраза "преждевременная оптимизация - корень всего зла" - это путь, путь к использованию. Для многих проектов это стало предлогом не учитывать производительность до конца проекта.

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

Я видел еще много "смешных" примеров немых проблем с производительностью, чем примеры проблем, возникших из-за "пессимизации"

  • Чтение одного и того же раздела реестра тысяч (или 10 тысяч) раз во время запуска программы.
  • Загрузка одной и той же DLL сотен или тысяч раз
  • Тратить мегабайты памяти, сохраняя полный путь к файлам без необходимости
  • Не организовать структуры данных, чтобы они занимали больше памяти, чем им нужно.
  • Определение всех строк, в которых хранятся имена файлов или пути к MAX_PATH
  • Беспроцентный опрос для вещей, имеющих события, обратные вызовы или другие механизмы уведомления.

Я думаю, что это лучшее утверждение: "Оптимизация без измерения и понимания - это вовсе не оптимизация - просто случайное изменение".

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

Ответ 3

Базы данных представляют собой пессимизирующую плэйленд.

Избранное включает:

  • Разделите таблицу на кратность (по диапазону дат, алфавитному диапазону и т.д.), потому что она "слишком большая".
  • Создайте таблицу архивов для записей, записанных в отставке, но продолжайте UNION с рабочей таблицы.
  • Дублировать все базы данных (подразделение/клиент/продукт и т.д.).
  • Сопротивление добавления столбцов в индекс, поскольку оно делает его слишком большим.
  • Создайте множество сводных таблиц, потому что пересчет из необработанных данных слишком медленный.
  • Создание столбцов с подполями для экономии места.
  • Денормализовать в полях-как-массив.

Это с моей головы.

Ответ 4

Я думаю, что нет абсолютного правила: некоторые вещи лучше всего оптимизированы заранее, а некоторые - нет.

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

С другой стороны, наши архитекторы программного обеспечения решили, что распакованные данные должны быть отформатированы в очень читаемом XML-документе и сохранены в нашей базе данных как таковая (в отличие от того, что каждое поле хранится в соответствующем столбце). Их идея заключалась в том, что "XML - это будущее", "дисковое пространство дешево", а "процессор дешев", поэтому нет необходимости оптимизировать что-либо. В результате наши 16-байтные пакеты были превращены в 2kB-документы, хранящиеся в одном столбце, и для даже простых запросов нам пришлось загружать мегабайты XML-документов в память! Мы получили более 50 пакетов в секунду, так что вы можете себе представить, насколько ужасна производительность (BTW, компания обанкротилась).

Итак, нет абсолютного правила. Да, иногда оптимизация слишком рано, это ошибка. Но иногда "cpu/disk space/memory cheap" девиз - настоящий корень всего зла.

Ответ 5

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

Вот пример:

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

Я: Почему вы это рассматриваете? В чем проблема, которую вы пытаетесь решить?

Он: Таблица X слишком широка, мы разбиваем ее на соображения производительности.

Me: Что заставляет вас думать, что он слишком широк?

Ему: Консультант сказал, что слишком много столбцов в одной таблице.

Me: И это влияет на производительность?

Ему: Да, пользователи сообщили о прерывистых замедлениях в модуле XYZ приложения.

Me:. Как вы знаете, что ширина таблицы является источником проблемы?

Ему: Это ключевая таблица, используемая модулем XYZ, и она похожа на 200 столбцов. Это должна быть проблема.

Me (Объяснение): Но в модуле XYZ, в частности, используются большинство столбцов в этой таблице, а используемые столбцы непредсказуемы, поскольку пользователь настраивает приложение для отображения данных, которые они хотят отображать из этой таблицы. Вероятно, что 95% случаев мы все равно присоединяемся ко всем столам, что повредит производительности.

Он: Консультант сказал, что он слишком широк, и нам нужно его изменить.

Я: Кто этот консультант? Я не знал, что мы наняли консультанта, и они вообще не разговаривали с командой разработчиков.

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

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

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

  • Отсутствующие индексы на несколько ключевых столбцы.
  • Несколько аналитиков-изгоев, которые периодически блокирующие столы для ключей (включая "слишком широкий" ) путем запроса производственной базы данных непосредственно с MSAccess.

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

Ответ 6

Я видел людей, использующих Alphadrive-7, чтобы полностью инкубировать CHX-LT. Это необычная практика. Более распространенной практикой является инициализация трансформатора ZT, так что буферизация уменьшается (из-за большей устойчивости к перегрузке) и создает байтографические изображения в стиле Java.

Полностью пессимистично!

Ответ 7

Я не согласен, но я поймал людей, использующих StringBuffer, чтобы объединить строки вне цикла в Java. Это было что-то простое, как поворот
String msg = "Count = " + count + " of " + total + ".";

в

StringBuffer sb = new StringBuffer("Count = ");
sb.append(count);
sb.append(" of ");
sb.append(total);
sb.append(".");
String msg = sb.toString();

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

  • StringBuilder несинхронизирован, поэтому должен быть предпочтительнее StringBuffer в случаях, когда ваш код не может быть вызван из нескольких потоков.
  • Современные компиляторы Java превратят читаемую конкатенацию String в оптимизированный байт-код для вас, когда она будет соответствовать в любом случае.

Ответ 8

Я однажды увидел базу данных MSSQL, которая использовала таблицу "Root". Таблица Root имела четыре столбца: GUID (uniqueidentifier), ID (int), LastModDate (datetime) и CreateDate (datetime). Все таблицы в базе данных были Foreign Key'd в таблице Root. Всякий раз, когда новая строка была создана в любой таблице в db, вам нужно было использовать пару хранимых процедур для вставки записи в корневую таблицу, прежде чем вы сможете добраться до фактической таблицы, о которой вы заботитесь (а не о базе данных, выполняющей работу для вы с несколькими триггерами простых триггеров).

Это создало беспорядок бесполезных подслушивающих и головных болей, потребовало что-то написанное поверх него, чтобы использовать sprocs (и устранить мои надежды на внедрение LINQ в компанию. Это было возможно, но просто не стоило головной боли), а наверху даже не выполнил то, что он должен был делать.

Разработчик, который выбрал этот путь, защитил его в предположении, что это спасло тонны пространства, потому что мы не использовали гиды на самих таблицах (но... это не GUID, сгенерированный в таблице Root для каждой строки we make?), как-то улучшили производительность и сделали "легким" аудит изменений в базе данных.

О, и диаграмма базы данных выглядела как мутантный паук из ада.

Ответ 9

Как насчет POBI - пессимизация, очевидно, с намерением?

Коллегия моей в 90-х годах устала от того, что ее исполнила только исполнительный директор, потому что генеральный директор провел первый день каждого выпуска программного обеспечения ERP (пользовательский) с определением проблем производительности в новых функциях. Даже если новые функции хрустят гигабайтами и сделают невозможным возможным, он всегда обнаружил какую-то деталь или даже, казалось бы, серьезную проблему, чтобы скулить. Он считал, что много знает о программировании и получил свои удары, отбивая программистов ослами.

Из-за некомпетентности критики (он был генеральным директором, а не ИТ-парнем), мой коллеги никогда не справлялся с этим. Если у вас нет проблемы с производительностью, вы не можете ее устранить...

До тех пор, пока за один выпуск, он не добавил много новых вызовов функции (Delphi) в новый код. Прошло всего 20 минут после концерта, и ему было приказано появиться в офисе генерального директора, чтобы лично получить его оскорбления.

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

Естественно, что мой коллеж теперь отдыхал в течение одного или двух дней за своим столом, улучшая свои навыки в Quake - затем на второй или третий день он удалил звонки с задержкой, перестроил и выпустил "аварийный патч", из которого он распространило слово, которое он провел 2 дня и 1 ночь, чтобы исправить дыры.

Это было первое (и единственное) время, когда злой генеральный директор сказал: "Отличная работа!" Для него. Что все это имеет значение, правильно?

Это был настоящий POBI.

Но это также своего рода оптимизация социальных процессов, поэтому она на 100% нормально.

Я думаю.

Ответ 10

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

Ответ 11

var stringBuilder = new StringBuilder();
stringBuilder.Append(myObj.a + myObj.b + myObj.c + myObj.d);
string cat = stringBuilder.ToString();

Лучшее использование StringBuilder, которое я когда-либо видел.

Ответ 12

Использование регулярного выражения для разделения строки, когда достаточно простого string.split

Ответ 13

Никто, кажется, не упомянул сортировку, поэтому я буду.

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

Ответ 14

Очень поздно в этой теме, я знаю, но я видел это недавно:

bool isFinished = GetIsFinished();

switch (isFinished)
{
    case true:
        DoFinish();
        break;

    case false:
        DoNextStep();
        break;

    default:
        DoNextStep();
}

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

Ответ 15

Худший пример, который я могу представить, - это внутренняя база данных в моей компании, содержащая информацию обо всех сотрудниках. Он получает ночное обновление от HR и имеет веб-сервис ASP.NET сверху. Многие другие приложения используют веб-службу для заполнения таких вещей, как поля поиска/выпадающего списка.

Пессимизм заключается в том, что разработчик считал, что повторные обращения к веб-службе будут слишком медленными, чтобы повторять SQL-запросы. И что он сделал? Событие запуска приложения читается во всей базе данных и преобразует все его в объекты в памяти, хранящиеся неограниченно до тех пор, пока пул приложений не будет повторно использован. Этот код был настолько медленным, что потребовалось 15 минут, чтобы загрузить менее 2000 сотрудников. Если вы случайно переработали пул приложений в течение дня, это может занять 30 минут или более, потому что каждый запрос веб-службы запускает несколько одновременных перезагрузок. По этой причине новые сотрудники не появлялись в базе данных в первый день, когда их учетная запись была создана, и поэтому не могли бы получить доступ к большинству внутренних приложений в первые пару дней, скрестив большие пальцы.

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

Ответ 16

Я когда-то работал над приложением, которое было заполнено следующим кодом:

 1 tuple *FindTuple( DataSet *set, int target ) {
 2     tuple *found = null;
 3     tuple *curr = GetFirstTupleOfSet(set);
 4     while (curr) {
 5         if (curr->id == target)
 6             found = curr;
 7         curr = GetNextTuple(curr);
 8     }
 9     return found;
10 }

Просто удалите found, вернув null в конец и изменив шестую строку на:

            return curr;

Удвоить производительность приложения.

Ответ 17

Мне приходилось пытаться модифицировать код, который включал эти драгоценные камни в классе Constants

public static String COMMA_DELIMINATOR=",";
public static String COMMA_SPACE_DELIMINATOR=", ";
public static String COLIN_DELIMINATOR=":";

Каждый из них использовался несколько раз в остальной части приложения для разных целей. COMMA_DELIMINATOR засорило код более чем 200 использованиями в 8 разных пакетах.

Ответ 18

Большое все время номер один, с которым я снова и снова сталкиваюсь во внутреннем программном обеспечении:

Не использовать функции СУБД для причин "переносимости", потому что "мы можем позже переключиться на другого поставщика".

Прочитайте мои губы. Для любой домашней работы: ЭТО НЕ ПРОИЗОЙДЕТ!

Ответ 19

У меня был сотрудник, который пытался перехитрить наш оптимизатор компилятора C и рутинный переписанный код, который только он мог прочитать. Одним из его любимых трюков было изменение читаемого метода, например (составление кода):

int some_method(int input1, int input2) {
    int x;
    if (input1 == -1) {
        return 0;
    }
    if (input1 == input2) {
        return input1;
    }
    ... a long expression here ...
    return x;
}

в это:

int some_method() {
    return (input == -1) ? 0 : (input1 == input2) ? input 1 :
           ... a long expression ...
           ... a long expression ...
           ... a long expression ...
}

То есть первая строка однократно читаемого метода станет "return", и вся другая логика заменит глубоко вложенные терниальные выражения. Когда вы пытались спорить о том, как это было недостижимо, он указывал на то, что сборка его метода составляла три или четыре инструкции сборки короче. Это было не обязательно быстрее, но оно было немного короче. Это была встроенная система, в которой иногда использовалось использование памяти, но было намного проще оптимизировать, чем это могло бы сделать код, который мог бы читать.

Затем, после этого, по какой-то причине он решил, что ptr->structElement был слишком нечитаемым, поэтому он начал менять все эти на (*ptr).structElement по теории, что он был более читабельным и быстрым.

Превращение читаемого кода в нечитаемый код не более 1%, а иногда и более медленный.

Ответ 20

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

Когда я врывался, я обнаружил, что первоначальный программист стремился ускорить процесс, распараллеливая анализ - запуск нового потока для каждого дополнительного источника данных. Тем не менее, он допустил ошибку в том, что все потоки требовали совместного ресурса, на котором они зашли в тупик. Конечно, все преимущества concurrency исчезли. Кроме того, он разбил большинство систем для запуска более 100 потоков, чтобы заблокировать все, кроме одного из них. Моя мудрая машина-разработчик была исключением из-за того, что она опрокидывалась через набор данных с 150 источниками примерно через 6 часов.

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

Ответ 21

Я предполагаю, что могу предложить этот камень:

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    // Find out how many bytes our value uses
    // so we don't do any uneeded work.
    if (value & 0xffff0000)
    {
        if ((value & 0xff000000) == 0)
            tmp = 3;
        else
            tmp = 4;
    }
    else if (value & 0x0000ff00)
        tmp = 2;

    switch (tmp)
    {
        case 4:
            ISQRT_INNER(15);
            ISQRT_INNER(14);
            ISQRT_INNER(13);
            ISQRT_INNER(12);
        case 3:
            ISQRT_INNER(11);
            ISQRT_INNER(10);
            ISQRT_INNER( 9);
            ISQRT_INNER( 8);
        case 2:
            ISQRT_INNER( 7);
            ISQRT_INNER( 6);
            ISQRT_INNER( 5);
            ISQRT_INNER( 4);
        case 1:
            ISQRT_INNER( 3);
            ISQRT_INNER( 2);
            ISQRT_INNER( 1);
            ISQRT_INNER( 0);
    }
#undef ISQRT_INNER
    return root;
}

Так как квадратный корень был рассчитан в очень чувствительном месте, у меня была задача изучить способ сделать его быстрее. Этот небольшой рефакторинг сократил время выполнения на треть (для комбинации аппаратного и компилятора YMMV):

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    ISQRT_INNER (15);
    ISQRT_INNER (14);
    ISQRT_INNER (13);
    ISQRT_INNER (12);
    ISQRT_INNER (11);
    ISQRT_INNER (10);
    ISQRT_INNER ( 9);
    ISQRT_INNER ( 8);
    ISQRT_INNER ( 7);
    ISQRT_INNER ( 6);
    ISQRT_INNER ( 5);
    ISQRT_INNER ( 4);
    ISQRT_INNER ( 3);
    ISQRT_INNER ( 2);
    ISQRT_INNER ( 1);
    ISQRT_INNER ( 0);

#undef ISQRT_INNER
    return root;
}

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

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

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1 << 30, root = 0;

    while (tmp != 0)
    {
        if (value >= root + tmp) {
            value -= root + tmp;
            root += tmp << 1;
        }
        root >>= 1;
        tmp >>= 2;
    }

    return root;
}

Это точно такой же алгоритм, хотя и немного отличается от реализации, поэтому я полагаю, что он квалифицируется.

Ответ 22

Это может быть на более высоком уровне, чем то, что вам нужно, но исправление (если вам разрешено) также связано с более высоким уровнем боли:

Настаивая на переносе Менеджера связей между объектами/Уровнем доступа к данным вместо использования одной из установленных, проверенных, зрелых библиотек (даже после того, как они были указаны вам).

Ответ 23

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

Ответ 24

Проверка перед каждой действительностью javascript, существует ли объект, с которым вы работаете,

if (myObj) { //or its evil cousin, if (myObj != null) {
    label.text = myObj.value; 
    // we know label exists because it has already been 
    // checked in a big if block somewhere at the top
}

Моя проблема с этим типом кода никому не кажется, что, если он не существует? Просто ничего не делать? Не сообщайте пользователям о себе?

Я согласен с тем, что ошибки Object expected раздражают, но это не лучшее решение для этого.

Ответ 25

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

Ответ 26

Как насчет экстремизма YAGNI. Это форма преждевременной пессимизации. Кажется, что в любое время, когда вы применяете YAGNI, вы в конечном итоге нуждаетесь в этом, в результате чего в 10 раз больше усилий, чтобы добавить его, чем если бы вы добавили его в начале. Если вы создадите успешную программу, то ваши шансы - ВАМ, ЧТОБЫ НУЖНО. Если вы привыкли создавать программы, чья жизнь быстро заканчивается, продолжайте практиковать YAGNI, потому что тогда я предполагаю YAGNI.

Ответ 27

Не совсем преждевременная оптимизация - но, конечно, ошибочная - это было прочитано на веб-сайте BBC из статьи, посвященной Windows 7.

Г-н Курран сказал, что команда Microsoft Windows все время анализировала все аспекты операционной системы для улучшения. "Мы смогли сбрить 400 миллисекунд с момента выключения, слегка подрезав музыку отключения WAV файла.

Теперь я еще не пробовал Windows 7, поэтому я могу ошибаться, но я готов поспорить, что есть другие проблемы, которые важнее, чем время, которое требуется для отключения. В конце концов, как только я увижу сообщение "Выключение Windows", монитор выключится, и я ухожу - как это помогает мне 400 миллисекунд?

Ответ 28

Кто-то из моего отдела однажды написал класс строки. Интерфейс вроде CString, но без зависимости от Windows.

Одна "оптимизация", которую они делали, заключалась в том, чтобы не выделять больше памяти, чем необходимо. По-видимому, не понимая, что классы причин, подобные std::string, выделяют избыточную память, так что последовательность операций += может выполняться в O (n) времени.

Вместо этого каждый += вызов принудительно перераспределил, который повторялся, добавляется в O (n²) Schlemiel the Painter алгоритм.

Ответ 29

Мой бывший сотрудник (a soab) был назначен для создания нового модуля для нашей Java ERP, который должен был собрать и проанализировал данные клиентов (розничная торговля). Он решил разделить КАЖДОЕ поле Calendar/Datetime в своих компонентах (секунды, минуты, часы, день, месяц, год, день недели, бисектор, триместр (!)), Потому что "как еще я буду запрашивать" каждый понедельник "?

Ответ 30

Не обижайтесь никому, но я просто оценил задание (java), которое имело этот

import java.lang.*;