Задать вопрос
  • Как ввести неопределённое количество строк С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если тут произвольная длина в смысле не "вам надо считать ровно 5 символов", то можно читать в std::string. Оно само выделит достаточно памяти.

    Вот так прочтется одно слово до пробела (или конца файла):
    std::string s;
    std::cin >> s;


    Вот так прочтется строка целиком до перевода строки (или конца файла):
    std::getline(cin, s);

    Потом можно по string проходится как по массиву, от 0 до s.length()-1.
    Ответ написан
    Комментировать
  • Алгоритм Рабина-Карпа. В чем ошибка?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Возможно там переполнение. Убедитесь, что у вас все хеши везде считаются только с участием unsigned типов. Переполнение в signed - это Undefined behavior.
    Ответ написан
    9 комментариев
  • Ошибка xmemory при return, как пофиксить?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Скорее всего, тип User нельзя вот так вот читать и писать в файл. Подозреваю, что там содержатся std::string, которые сами в себе хранят лишь указатели на символы в строке. Поэтому, если std::string записать в файл как набор байт, то вы запишете в файл указатели. Прочитав их назад из файла, вы получите случайне адреса, не указывающие ни на что.

    Вам придется писать руками ввод и вывод типа из файла.
    Ответ написан
    1 комментарий
  • Как правильно решить задачу про кузнечика путём динамического программирования?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Вы поняли, что это динамическое программирование. Опишите, что у вас за функция ДП, дайте формулу пересчета, базу и где ответ.
    Ответ написан
  • Как реализовать такую функцию где надо используя аргументы (+ - / *) вставляя между цифрами получить заданное чисто. Как вывести все результататы?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Только перебор всех возможных вариантов.
    Ответ написан
    Комментировать
  • Как реализовать Дискретное косинусное преобразование изображение в Python самому, не прибегая к библиотеке?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Преобразование определено над матрицей NxN. В формулах в учебнике f(u,v) - это значение пикселя в ячейке c индексами u, v. Вам надо тупо реализовать формулы из учебника (4 вложенных цикла).

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

    Но это не относится к самому преобразованию. Это тонкость алгоритма jpeg.
    Ответ написан
    Комментировать
  • Как считать максиминный способ в нечетких множествах?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Ну вот у вас в формуле же написано, что U объединения, это максимум из двух U. Ваши два U - это линии на графике. Надо брать верхнюю из них для каждого x.
    Ответ написан
  • Как передать в лямбда функцию два аргумента?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам поможет std::bind.

    Передавайте в partition
    std::bind(predicate, item.first, std::placeholders::_1)
    в качестве предиката.

    Edit:

    Но тут у вас будет другая проблема. set - не vector. Вы не сможете его передать stable_partition. Вместо ручного применения stable_partition, используйте erase_if. Предикат туда также через std::bind передавайте.
    Ответ написан
    2 комментария
  • Как сделать вектор char беззнаковым числом?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Похоже практически все встроенные функции ожидают '\0' на конце входного буфера, что не ваш случай.

    Единственное исключение, которое я нашел - std::from_chars. Только оно далеко не везде доступно и надо подключать charconv.

    Еще можно руками, если точно известно, что никаких ошибок в числе нет:
    unsigned int vtoi(const std::vector<char> &a) {
      unsigned int res = 0;
      for (const auto& c: a) {
        res = 10*res + static_cast<unsigned int>(c) - static_cast<unsigned int>('0');
      }
      return res;
    }


    Проверки на переполнение и левые символы добавьте сами, если надо.
    Ответ написан
    Комментировать
  • Как узнать степень числа, которая является средним арифметическим степеней двух чисел?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Странное задание. Какая польза от этого сокращения сравнений, если всего в результате вставки переместится до O(log n) элементов?

    Но, если так надо, то вам нужно для каждого числа сначала узнать номер старшего ненулевого бита (most significat bit - MSB), и потом сдвинуть верхнее число вправо на половину разницы в позициях старших битов.

    1 = 0000001b, msb = 0
    18 = 0010010b, msb = 4

    Разность - 4 разряда. Значит, надо сдвигать на 2 разряда вправо:
    18 >> 2= 0010010b >> 2 = 00100b = 4

    Еще пример: для 4 и 18 msb были бы 2 и 4, разность -2. Сдвинув 18 на 2/2=1 разряд вправо, вы бы получили 9.

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

    Еще можно подсчитать msb только один раз для правой границы бинпоиска, а потом просто помнить его, ведь у средней точки - это среднее арифметическое (левая граница изначально 1 - у нее msb = 0). А потом в процессе бинпоиска надо просто хранить msb для двух границ и заменять известным значением середины один из концов.

    Для предподсчета просто в цикле задавайте msb[i] = msb[i/2] + 1;
    Ответ написан
    Комментировать
  • Как выглядит стандартное решение эллипса по центру и 3 точкам?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    TL;DR:
    S = Pi*sqrt(3 / [ (1/L1+1/L2+1/L3)^2-2*(1/L1^2+1/L2^2+1/L3^2) ])

    тут L1, L2, L3 - квадраты трех измерений.

    Вывод формул:
    Чуть-чуть аналитической геометрии и куча элементарной алгебры помогут вам вывести эти уравнения.
    Если ввести систему координат с осями по главным радиусам эллипса, то уравнение эллипса будет:
    x^2/a^2+y^2/b^2 = 1

    При этом все точки под углом alpha к большой полуоси будут на луче:
    x(t, alpha) = t*cos(alpha)
    y(t, alpha) = t*sin(alpha)


    Обозначим синус и косинус угла для первого измерения как:
    s = sin(a1), c = cos(a1)

    Пусть квадраты расстояний - L1, L2, L3.

    Если пересечь луч и эллипс, то можно составить уравнение для длины вдоль угла a1 (первое измерение), просто подставив известные x(a1, sqrt(L1)) и y(a1, sqrt(L1)).
    1/L1 = c^2/a^2+s^2/b^2

    Для остальных измерений надо прибавлять 120 градусов к углу под cos и sin. Если раскрыть cos(120+a1) = cos(120)cos(a1)-sin(120)sin(a1) и sin(120+a1) = cos(120)sin(a1)+sin(120)cos(a1), то можно составить еще 2 уравнения:

    1/L2 = (-1/2*c-sqrt(3)/2*s)^2/a^2+(sqrt(3)/2*c-1/2*s)^2/b^2
    L3 = (-1/2*c+sqrt(3)/2*s)^2/a^2+(-sqrt(3)/2*c-1/2*s)^2/b^2


    Всего с учетом тригонометрического тождества s^2+c^2=1 у нас 4 уравнения на 4 неизвестных a, b, c, s.

    Но нам не нужны все значения. Площадь эллипса Pi*a*b, а радиусы эллипса - a и b.

    Раскрыв квадраты выше и всячески складывая эти уравнения можно получить в итоге
    1/a^2+1/b^2 = 2/3*(1/L1+1/L2+1/L3)
    1/a^2*b^2 = [ (1/L1+1/L2+1/L3)^2-2*(1/L1^2+1/L2^2+1/L3^2) ]/3


    Отсюда площадь:
    S = Pi*ab = Pi*sqrt([ (L1+L2+L3)^2-2*(L1^2+L2^2+L3^2 ]/3)


    Чтобы найти радиусы эллипса, вам надо найти a и b. Выше уже даны два уравнения для суммы и произведения 1/a^2 и 1/b^2 - можно из них получить квадратное уравнение для t=1/a^2. Два его решения и будут вашими радиусами эллипса (не забудьте взять корни и обратить). Тут надо аккуратно подставить выражения в школьные формулы для квадратного уравнения.
    Ответ написан
    9 комментариев
  • Правильно ли я делаю?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Не совсем. Форма правильная, но пропорции - нет. График должен начинаться в той же точке, что и u_b. Число 0.5 там не верно. Эта точка значительно ниже 0.5. И точка пересечения двух графиков вовсе не x=4.
    Ответ написан
  • Можно ли объявить и реализовать шаблонный метод класса в исходном файле в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Нет, все методы класса надо объявить в хедере (тем более публичные): иначе как пользователи класса смогут к нему обращаться? С простыми функциями так можно, если они не используются где-то извне. Или с классном можно, только если он весь целиком объявлен в cpp файле и, соответственно, его нельзя использовать вне этого файла.

    Можно еще перенести в cpp файл определение шаблонных классов/методов/функций, но для этого надо в хедере указать через forward declaration все используемые специализации шаблона. Например так:
    template <>
    int Database::RemoveIf<bool>(bool predicate);


    Конечно, там должен быть не bool а тип вашего предиката. И надо такие штуки воткнуть в хедер для ВСЕХ типов, которые в других файлах пихаются в шаблон.

    Обычно нужно определять функцию прямо в хедере, потому что когда компилятор собирает cpp файл с определением класса, он не видит, как этот шаблон используется в других файлах, поэтому он не может догадаться сгенерировать код для используемых специализаций шаблона. Если же реализовывать функцию в хедере, то реализация будет в том же файле, что и ее использование. Поэтому компилятор сможет выбрать нужные типы. Forward declaration позволяет обойти эту проблему.
    Ответ написан
    3 комментария
  • Как правильно поменять значения?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Судя по коду, вы хотите, чтобы массив был отсортирован. Но тогда просто менять новый элемент с чем-то в массиве неправильно - его надо туда вставлять, сдвигая все элементы.

    Вот пример: уже обновленная и отсортированная часть {1, 2, 3, 5, 6, 7}. Только что обновленный элемент имеет значение 4. lower_bound вернет итератор на 5. Вы поменяете 5 и 4 и получите {1, 2, 3, 4, 6, 7, 5} - не отсортировано уже.

    Можно удалить элемент в it и вставить на новое место через insert, но тогда могут быть проблемы с итератором цикла. Можно ручками через swap сдвигать элементы в цикле:
    T tmp = it->value;
    for (auto cur = std::lower_bound(vector.begin(), it, (*it)); cur < it; ++cur) {
       swap(tmp, cur->value);
    }
    it->value = tmp;


    Это, фактически, будет сортировкой вставкой за O(N^2). lower_bound за логарифм тут на самом деле даже лишнее и только замедляет сортировку. Лучше одним циклом сразу и swap-ать и сравнивать элементы.

    Но еще быстрее будет отдельно пройтись по массиву и обновить его целиком и потом вызвать std::sort для сортировки по value.
    Ответ написан
    Комментировать
  • Является ли эффективность данного алгоритма O(n*log(n))?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Нет, тут O(n^2). С чего вы там взяли log?
    Ответ написан
    1 комментарий
  • Как оптимизировать алгоритм подсчёта остатка на складе по системе LIFO (последний пришел первый ушел)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Надо сделать по нормальному, без таблиц, с использованием стека, который можно сделать просто тупо списком.

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

    При приходе in, вы добавляете в стек (через append у list-а) пару (цена, количество).

    При приходе out, вы берете из стека с верхушки записи, пока не наберете нужное количество и уменьшаете количество. В конце пеобразуйте список в таблицу, если надо.

    Что-то вроде такого (сам не питонист, возможно придется переписать немного)

    def getOstatokLIFO(df):
      stack = [];
      for index, row in df.iterrows():
        if row.operation == "in":
          stack.append([row.price, row.quantity])
          continue
        left = row.quantity
        while left > 0:
          if left >= stack[-1][1]:
            left -= stack[-1][1]
            stack.pop()
          else:
            stack[-1][1] -= left
            left = 0
            
      return stack


    Но вообще, DataFrame очень медленно работет при такой последовательной обработке, поэтому я бы посоветовал вам не создавать pandas dataframe изначально, и получить ваши данные в виде списка словарей, touples или объектов. А алгоритм расчета предполагает последовательную обработку.
    Ответ написан
    Комментировать
  • Тема: Операции над нечеткими множествами. Кто может объяснить задачу?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Перечитайте теорию. Повторите определение нечеткого множества, функии его принадлежности и операции над нечеткими множествами. Что значит НЕ B? Раз вероятность принадлежать B - это f(x), то вероятность не принадлежать, очевидно - 1-f(x). Вот и на рисунке 2 показана функция 1-f(x), где f(x) показана на графике для b.

    С пересечениями, наверно, функции перемножаются, а при объединении берется 1-(1-f(x))(1-g(x)).
    Ответ написан
  • Массив: Повернуть массив V на 90° и занести в массив Н все парные элементы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ну нарисуйте на бумажке матрцу, скажем 4x4, заполните числами от 1 до 16 и рядом нарисуйте ее же повернутую на 90 градусов. Посмотрите внимательно, куда попадают числа. Возьмите произвольную ячейку [i][j] и подумайте, куда она в итоге попадает. Если не можете так сообразить, выпишите для чисел 1,2,5,7,13 их индексы в первой и второй матрице в 4 столбика и посмотрите на закономерности между индексами.
    Ответ написан
    Комментировать
  • Как найти количество путей в невзвешенном графе с символами в узлах?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Точно также, как ищите наидлиннейший путь. Будет у вас DFS, который возвращает количество путей из заданной вершины до конечной, с заданными уже посещенными вершинами. В нем перебираете все исходящие ребра, запускаетесь рекурсивно (если конец ребра не посещен уже) и суммируете все результаты. Если пришли в конечную вершину - то возвращаете 1 (1 путь длины 0 - уже пришли). В начале функции помечайте вершину посещенной, чтобы в нее опять не входить. В конце функции помечайте вершину не посещенной, чтобы можно было другие пути через эту вершину считать. Разница с самым длинным путем в том, что вы тут суммируете результаты всех рекурсивных вызовов DFS, а не берете максимум. Ну и еще +1 не надо, как к длине, прибавлять.

    Если граф ациклический, то можно использовать мемоизацию: результаты вычисления DFS для каждой начальной вершины сохраняйте (в глобальный массив, например) и никогда не считайте заново. При каждом вызове проверяйте, а не подсчитано ли значение уже и возвращайте его.
    Ответ написан
  • Как посчитать сумму цикла?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Ну, вот вы числа вывели. Теперь вместо вывода прибавляйте их к переменной сумме, которая 0 перед циклом.
    Ответ написан
    Комментировать