Обновить
9

Пользователь

24
Подписчики
Отправить сообщение
Обоснуйте костыль.
Ё это не Е с умляутом или диэрезисом.
NFD-нормализация в Python с Вами не согласна:

>>> list(unicodedata.normalize('NFD', chr(1105)))
['е', '̈']
Когда-то были времена, когда еще не существовало ни инсталляторов, ни толком Windows, жесткие диски были маленькими, а найти нужный разархиватор для экзотического формата типа rar было не так просто. Поэтому если бы не было необходимости в SFX-архивах, то их бы и не реализовывали лидеры индустрии — ARJ, например, или HA.
В своем предыдущем комментарии я привел код реализации, которую я не могу назвать совсем уж оптимальной, но которая, во всяком случае, как минимум в несколько раз быстрее регулярных выражений, и предложил вам оценить скорость ее работы по сравнению с вашим "простым решением". Пространство для оптимизации по скорости выполнения присутствует — можно, например, сделать inplace-версию, т.к. это более частый сценарий использования.

Писать статью для тривиального решения? Зачем? Максимальное значение кодепоинта юникода — 0x10FFFF, значит, битовая карта из 0x110000 бит покроет весь диапазон, а для хранения этой карты достаточно 17408 значений по 64 бита каждое. Проходимся по списку фильтруемых символов, заносим их в битовую карту. Проходим по строке, и если знак отсутствует в битовой карте, то дописываем его в конец результирующей строки. Если место в результирующей строке закончилось, то увеличиваем ее в 1.25 раз, а в конце отрезаем хвост по фактической длине, включая терминатор. Мое решение еще включает два частных случая — когда в списке фильтров нет ни одного символа вообще (строка просто копируется), и когда там один символ (можно обойтись без битовой карты). В принципе, можно еще было бы сократить потребление памяти, если сначала выделять битовую карту на 28 бит, и увеличивать ее до 216 бит при использовании соответствующих символов, и только затем поднимать до 221 при выходе за пределы BMP.

К чему очередная мусорная статья "Как я писал Hello world", если подобное реализует любой начинающий программист?
Ну, RAR-архивы бывают с расширением EXE — самораспаковывающиеся, они же SFX (self-extracting). Хуже, когда это whatever.mp3.exe.
Самое простое решение может быть не самым удачным только в двух случаях
В теории разницы между теорией и практикой нет — а на практике есть. Вся проблема в т.н. «дырявых абстракциях» — большинство вещей устроено намного сложнее, чем позволяет предположить их внешний интерфейс. Примеров множество — конкатенация строк в цикле без использования StringBuilder-а, побайтовое копирование памяти, работа с сетевыми ФС как с локальными, перемещение файлов между границами разделов, «заторы» в TCP, использование регулярок без кэша, и т.д.

Насчет «статистики» — простите, а какого вида статистику вы ожидаете? Внутри NSRegularExpression не магия происходит — посмотрите исходники, почитайте, как в принципе работают регулярные выражения, и какой оверхед имеет компиляция регулярного выражения (токенизация, разбор в AST, генерация байткода и его последующее выполнение). То, что у вас речь не идет о романах объема «Войны и мира», только усугубляет ситуацию, т.к. на маленьких строках компиляция регулярок займет больше времени, чем непосредственно обработка.

Любопытства ради, проведите тест по производительности, и скажите, на каких начальных данных ваш код окажется быстрее?
Сниппет
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

typedef uint32_t ucs4_t;

#define DEFAULT_CAPACITY  16
#define CAPACITY_MULTIPLIER  125

ucs4_t *strip(const ucs4_t *restrict string, const ucs4_t *restrict chars) {
    ucs4_t single_ch = *chars++;

    if (!single_ch) { // no filter chars
        size_t size;
        {
            const ucs4_t *string_top = string;

            while (*string_top++) { };

            size = sizeof(ucs4_t) * (string_top - string);
        }

        ucs4_t *restrict result;
        if (!(result = malloc(size))) {
            return NULL;
        }

        memcpy(result, string, size);

        return result;
    }

    size_t size = DEFAULT_CAPACITY;
    ucs4_t *result_base, *result_top, *result;
    ucs4_t *_result_base;
    ucs4_t ch;

    bool single_mode = !*chars;
    uint64_t *bitmap = NULL;

    if (!single_mode) {
        if (!(bitmap = calloc(1, 0x110000 / sizeof(*bitmap)))) {
            return NULL;
        }

        chars--;
        while ((ch = *chars++)) {
            bitmap[ch / 64] |= 1 << (ch % 64);
        }
    }

    if (!(result_base = result = malloc(size))) {
        goto fail;
    }
    result_top = result_base + size;

    while ((ch = *string++)) {
        if (single_mode) {
            if (ch == single_ch) {
                continue;
            }
        } else {
            if (bitmap[ch / 64] & (1 << (ch % 64))) {
                continue;
            }
        }

        *result++ = ch;

        if (result == result_top) {
            size_t offset = size;

            size = 1 + size * CAPACITY_MULTIPLIER / 100;

            if (!(_result_base = realloc(result_base, size))) {
                goto fail;
            }
            result_base = _result_base;

            result_top = result_base + size;
            result = result_base + offset;
        }
    }

    *result = 0;
    if (!(_result_base = realloc(result_base, sizeof(ucs4_t) * (result - result_base + 1)))) {
        goto fail;
    }
    result_base = _result_base;

    return result_base;

fail:
    free(bitmap);
    free(result_base);
    return NULL;
}

// Пример вызова: ucs4_t *result = strip(U"zqHeqllzo, __qwzor_lzd!q_q", U"zq_");

Пользоваться моим кодом в результате не сложнее, чем вашим — прошу лишь извинить, что я не знаю ObjC и поэтому не могу привести NSString к массиву codepoint-ов самостоятельно.

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

Ну и вы никак не прокомментировали, каким образом короткая реализация поможет пользователю библиотеки, который все равно в исходники заглядывать не будет (пока что-нибудь не сломается), и будет использовать одну лишь функцию?
Что подозрительного в SFX-архивах как таковых? Подозрительно, если архиватор не признает в SFX сам архив.
Далеко не всегда самое короткое решение — самое удачное с точки зрения производительности и/или потребления памяти. Например, компиляция регулярного выражения — ужасно ресурсоемкий процесс, по сравнению с проходом по строке и фильтром по таблице.

Более того, если вы предоставляете библиотеку, то какая разница конечному пользователю, сколько строк занимает реализация той или иной функции? Все равно для пользователя это единственный вызов.
С удивлением обнаружил боковые колесики у этого агрегата. Т.е. держать равновесие оно не умеет — а чем он, в таком случае, отличается от обычной радиоуправляемой машинки?
И тут статья переезжает в хаб "3D-печать".
От банка и страны зависит, наверное.
Так образец-то на мониторе выводится — хотел бы я посмотреть, как вы его переклеивать собираетесь :)
Точно, и понаделывать всяких LIDRов (Local ID Registry), RIDRов (Regional ID Registry), еще до кучи PIDRов каких-нибудь, простихоспади. "Купи десять ID и получи первый год со скидкой 50%! Всего $1999, только сейчас!"
Даешь Яндекс-браузер единственным разрешенным браузером!)))))))))))
Плохой, нехороший автор сайта! Надо было владельцу сайта позаботиться о своей совместимости с Яндексом! Куда он смотрел вообще? Он понимал, кому дорогу переходит, на кого вообще тэг открывает?

Надо решить проблему радикально — просто все владельцы сайтов должны будут перед размещением получить у Яндекса соответствующее разрешение, подтверждающее совместимость сайта с техническими возможностями Яндекса, а также его целями и намерениями. Естественно, не бесплатно.
Ну, эта штуковина выглядит монолитной, и, возможно, защелкивается — иначе бы она отваливалась от терминала, так ведь? Банкоматы всегда говорят "убедитесь, что внешний вид банкомата соответствует образцу", т.е. есть, с чем сравнивать — с чем сравнивать терминалы? Ну и накладки на банкомат оставляют щели по краям — а тут как, переворачивать терминал пузиком кверху?
Как защититься от подобной хрени? Банкомат-то можно пальцем поковырять, а тут как?
Но ведь можно просто с некоторой периодичностью обрубать историю. Например, каждые 5 лет создавать "снапшот" состояния сети — а именно, на каком кошельке сколько денег, и какие есть активные транзакции на момент взятия снапшота. Таким образом, все, что было до, можно будет удалить. Да, потеряется возможность проследить каждую монету до ее рождения, но так ли это нужно на промежутках в пять лет? Те, кому это действительно нужно, смогут хранить у себя полную версию дерева, например.
Поздравляю с первым комментарием! ;)
биткоИн по-русски должен тогда произноситься так же, как упомянутый «воин»
Вы это так пишете, будто оно произносится как-то иначе — «биткоин», «сирлоин», «кот-воин» и т.д.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность

Специализация

Архитектор программного обеспечения