Архив рубрики: Программирование

Почему мне перестал нравиться Qt

Когда-то давным давно я полюбил Qt. Он был простой, с качественной документацией, наличием своей среды разработки. В нем были свои контейнеры QHash, QMap, QVector и после них, глядя на std, становилось сильно плохо.

Все изменилось в 2013-ом году, когда компиляторы gcc и clang начали полноценно поддерживать C++11. Этот факт прошел мимо меня, что и неудивительно. Все важные события нужно отслеживать самому.

Для понимания всей картины рекомендую посмотреть доклад от разработчика Qt: https://youtu.be/uZ68dX1-sVc?t=29m20s
Читать далее

Пущинская новогодняя олимпиада 2018

Месяц назад мы провели очередную Пущинскую новогоднюю олимпиаду.

В этот раз мы были особо амбициозны, и ровно по этой причине мы получили кучу проблем. Задачи писало аж пять человек — я с Арсением, Леша Соловьев, Данила Сорокин и Татьяна Ивановна. Кроме того, Женя Баулин тусовался в нашем google doc, где он помогал исправлять грамматические и логические ошибки.

Сам google doc с задачами был создан более чем за 2 месяца до олимпиады, но задач в нем не было. Обычно мы с Арсением начинали с пары задач, потом кое-как состыковывались друг с другом, получали сюжет, определяли необходимую сложность и количество задач.

Не в этот раз.

Читать далее

Сборка BSA-Analytics под Windows 10

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

  1. 2 года назад все стабильно работало
  2. Под линуксом все и сейчас стабильно работает
  3. Под виртуалкой и под линуксом все работает
  4. Под чужой Windows 7 все работает
  5. Версия полугодовалой давности везде работает
  6. Никаких изменений за последние полгода, которые могли бы сказаться, не было. Тем не менее, все сломалось
  7. На рабочем компе Windows 8.1, которая затеяла массивное обновление самой себя некоторое время назад

Читать далее

Как перекодировать всю коллекцию музыки одной командой

Дано:
1) Весь Король и Шут, скачанный с рутрекера в формате *.m4a, с кодеком alac (apple lossless codec)
2) Skoda Octavia III, которая читает m4a, но не переносит проприетарные кодеки (как и я)

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

find . -iname "*.m4a" -execdir sh -c 'ffmpeg -i "$0" -acodec flac "$(basename "$0" .m4a)".flac' "{}"  \;
find . -iname "*.m4a" -execdir sh -c 'ffmpeg -i "$0" -acodec mp3 -b:a 320k "$(basename "$0" .m4a)".mp3' "{}"  \;

И финализация только после проверки, что все прошло удачно:

find . -iname "*.m4a" -execdir rm "{}" \;

Сага о скорости sscanf

В нашем проекте есть одно из мест при чтении, когда надо распарсить строчку с числами вида «{ 123, 234, 345, 456, 567 }». Там всегда стоял сишный код декодирования через scanf. Ну а потом там пришлось все переделывать, и я на автомате написал декодирование в Qt стиле. А потом решил проверить что же будет быстрее.

Итого, у нас 2 варианта:
1) Ищем каждую первую цифру из каждого из чисел, после чего натравливаем scanf()
2) Сплитим строчку по разделителю, после чего для каждой полученной строки исполняем QString().toInt()

Для проверки что же работает быстрее я написал следующий код:

#include <QCoreApplication>
#include <QtGlobal>

#include <QElapsedTimer>
#include <QString>
#include <QStringList>
#include <QDebug>

#include <stdio.h>

int main(int argc, char *argv[])
{
    QByteArray r;
    for (int i = 0; i < 1000000; i++) {
        float a;
        int b = rand();
        a = *reinterpret_cast<float*>(&b);
        r += QString::number(rand()).toUtf8() + '\0';
    }

    //------------------------------------------
    //------------------------------------------

    QElapsedTimer timer;
    timer.start();

    QList<QByteArray> l = r.split('\0');
    float res = 0;
    for (int i = 0; i < l.size(); i++) {
        res += l.at(i).toFloat();
    }

    qDebug() << res << timer.elapsed();

    //------------------------------------------

    timer.start();

    const char *data = r.data();
    int size = r.size() - 1;
    res = 0;
    float f;
    for (int i = 0; i < size; i++)
        if (data[i] == '\0') {
            sscanf(data + i + 1, "%f", &f);
            res += f;
        }

    qDebug() << res << timer.elapsed();

    return 0;
}

Дебаг сборка
Qt: 165мс на декодирование
Си: 171мс на декодирование

Релиз сборка
Qt: 144мс
Си: 153мс

Массив чисел можно генерить как из целых, так и из float — скорость от этого особо не изменится. Зато скорость знатно меняется, если в качестве разделителя использовать не \0, а, допустим, просто пробел.

В таком случае, если уменьшить количество чисел с 1000000 до 100000, скорости будут такими (релиз):
Qt: 18мс
Си: 963мс

Знаете что это значит? Это значит, что если втупую написать код на Си, ожидая что он будет работать быстрее, то он не только может оказаться медленнее, он может совершенно случайно начать работать за квадрат вместо линии, которую обеспечивает Qt. Остается только догадываться насколько эффективно можно использовать еще более быстрый инструмент — ассемблер.

«Программист, наверное»

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

Постучался, захожу:
— Здравствуйте, я работаю в Квант-программ. Эта бухгалтерия обслуживает эту фирму, верно?
— <какой-то невнятный ответ>
— Вы Анна да? Очень приятно познакомиться, вот 2 заявления на отпуск.
Мне мужчина в спину кидает:
— Программист, наверное
Я его спрашиваю, вы, мол, как так на глаз определяете?
На что он отвечает:
— Все люди как люди, бестолковые. И только программисты пытаются полностью выстроить логику поведения и начинают путаться, если что-то идет не по плану.

Ровно описание моего поведения во всех ситуациях.

О накопившихся багах

Мне тут оказалось нужно как-то объяснить железячникам как кодировать и декодировать сообщения нашего формата. Прикинув сколько у нас Qt-контейнеров начал разбираться что же происходит после исполнения команды вида:
QDataStream() < < QDateTime() << QString() << QVector()

Для этого пришлось залезть в исходники Qt 4.8.6, где мой глаз зацепился за этот ужас:

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

Читать далее

Пущинская новогодняя олимпиада 2017

Неделю назад провели нашу очередную олимпиаду. На этот раз по новым правилам, но вроде бы получилось неплохо. Самая сильная сюжетная линия из всех, которые у нас были, да и самих задач целых 12 штук. 3 города — Пущино, Дубна и Дмитров. В двух лигах из трех Пущино победило.

Отказывало все подряд, все некритично. Условия пришлось заливать на ftp сервер, что могло быть чревато, если бы мой сайт не был бы в white листе цензоров целиком. Уже после олимпиады починил в nginx’е отправку больших client_body_size. Это не лимит php, это что-то в nginx’e и wordpress’e.

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

Еще я первый раз увидел участника из четвертого класса. Не знал что так бывает, но времени у него, конечно, еще много.

Russian AI Cup

Каждый год господа из mail.ru придумывают очередную игру для соревнования стратегий.

Я участвовал в CodeTanks, но с аккаунта, который уже не существует. Место у меня там было в районе 500ого, но всех знакомых я тогда обогнал.

Я участвовал в CodeTroopers, но тогда мне не было 18, и претендовать на призы я не мог. Что, впрочем, не помешало мне получить футболку и забрать места из начала второй сотни.

Я формально участвовал CodeHockey, но так и не научился забивать шайбы в ворота, так что у меня быстро исчез интерес.

Я участвовал в CodeRacing, но моя стратегия была всего лишь заглушкой. Мне тогда было очень весело получать свою футболку на соплях — это было крайне высокое отношение цена/качество. Тем не менее, я до сих пор жалею, что не отправился за первым местом. Моих знаний и навыков хватило за то чтобы потолкаться в финале, генетический алгоритм для поиска оптимальной траектории это вполне по мне. Но тогда катастрофически не хватало времени.

Я не участвовал в CodeWizards, потому что Дота — вселенское зло, и ее отголоски надо презирать и уничтожать. Короче, было неинтересно.

Я не собирался участвовать в CodeWars. Мне было непонятно какую стратегию писать. Но меньше чем за неделю до первого раунда я посмотрел на количество участников — чуть больше 500 — и решил отправиться за халявной футболкой. Простейшая заглушка дошла до ~220ого места, так что я остался вдохновлен. После этого рейтинг начал падать и грохнул кучу времени в Стратегию. Стратегия оказалась на редкость хреновой, допилить ее до конца я не успел, но времени грохнул тьму. В первом раунде вошел в топ-100.

Текущее состояние CodeWars. Несколько минут назад завершился первый раунд

Короче, я отправляюсь за толстовкой. Цель — попасть в топ-50. До встречи через 2 недели.

Школьная олимпиада по программированию 2017

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

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

Около 550 посылок. Я на этот раз сделал героический поступок — я посмотрел все прошедшие решения, и примерно половину зафейлившихся. На этих задачах конечно особо не разойдешься, но интересные посылки были.
Читать далее