• Как обрезать путь чтобы осталось только имя файла?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    for file in filename: переберет в file все символы строки filename.

    Вам надо просто передавать ваш filename в open.
    Ответ написан
    Комментировать
  • Алгоритм для нахождения количества пересечений отрезков в последовательности(списке)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Заведите массив из нулей. Для каждого отрезка сделайте +1 в координату его левого конца и -1 в координату, следующую за правым концом.

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

    Это если вам надо весь массив, как в примере, выводить. Не знаю специфику вашей задачи, может эффективнее будет класть в массив пары {координата, +-1} и сортировать. Потом точно также обойти слева направо поддерживая счетчик.
    Ответ написан
    4 комментария
  • Как понять цифры хэмминга на пальцах?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Генерируются они так:

    Есть у вас список уже сгенеренных чисел, изначально содержит только 1.

    Вы добавляете в список сделющее число, пока не наберете необходимое количество.

    Поддерживайте 3 указателя (изначально на первое число), которые указывают на первые неиспользованные числа для домножения на 2, 3 и 5.

    Каждый раз берете и сморите что лучше - взять число из первого указателя, домножить на 2, взять число из второго домноженное на 3 или из последнего указателя и домножить на 5. Кладете это число в список и сдвигаете указатель.

    Пример:
    шаг 1.
    указатели: 1, 1, 1
    список: {1}
    варианты:1*2, 1*3, 1*5. Лучший - 2.

    шаг 2.
    указатели: 2, 1, 1
    список: {1, 2}
    варианты:2*2, 1*3, 1*5. Лучший - 3.

    шаг 3.
    указатели: 2, 2, 1
    список: {1, 2, 3}
    варианты:2*2, 2*3, 1*5. Лучший - 4.

    шаг 4.
    указатели: 3, 2, 1
    список: {1, 2, 3, 4}
    варианты: 3*2, 2*3, 1*5. Лучший - 5.
    Ответ написан
  • Как вырезать участки из числа и получить остатки?

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

    Удобный трюк - сдвинуть начала отрезков на 1 влево, чтобы отрезок, вырезающий число 1 (1..1) был длиной 1.
    Представьте, что у вас на числовой прямой 10000 единичных кусочков, с 0 до 10000 - это ваши изначальные числа. Если вы хотите вырезать отрезок 5..7 (числа 5, 6 и 7), то вам надо на этой прямой вырезать отрезок [4...7] - от точки 4 до точки 7.

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

    php не знаю, вот вам на C++. Спрашивайте, если что непонятно:
    vector<pair<int, int>> CutOutSegments(int begin, int end, vector<pair<int, int>> segments)
      // Массив из пар чисел. Пустой массив, в который будем добавлять строки из 2 чисел.
      vector<pair<int, int>> events; 
      events.push_back({begin-1, 1});  // добавляем строку с числами begin и 1.
      events.push_back({end, -1});
      for (auto s: segments) {
         events.push_back({s.first-1, 1});  // s.first - начало отрезка.
         events.push_back({s.second, -1});  // s.second  - конец отрезка.
      }
      sort(events.begin(), events.end());
      int prev_pos = events[0].first;
      int count = 0;
      vector<pair<int, int>> result;
      for (auto e: events) { // e - строка массива events. e.first/second - 2 числа в ней.
        if (prev_pos < e.first && count == 1) {
          result.push_back(prev_pos + 1, e.first); // добавялем +1, что бы отрезок [0, 1] был выдан как одно число 1..1.
        }
        count += e.second;
        if (e.first == end) break;
      }
      return result;
    }


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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Есть неалгоритмический способ ускорить ваше решение - храните в каждой ячейке массива не одну цифру - а несколько. Фактически, проводите вычисления в системе счисления 10000, вместо 10. Или даже 1000000000 - но тогда надо временные вычисления (умножение) делать в int64_t, чтобы переполнения не было.

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

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

    Но в таком виде алгоритм будет даже медленнее на больших числах. Ему потребуется O(log K) умножений большого на большое (которое делается за O(L^2), где L - длина числа, которая будет O(K)). Итоговая сложность этого алгорима будет O(K^2 log K).

    Когда как ваше текущее решение делает K коротких умножений (Каждое - O(K)) - всего O(k^2) операций. Но если применять быстрое умножение длинных чисел через быстрое преобразование Фурье то итоговая сложность будет O(K log^2 K log log K). Для power=100 особо вы разницы не почуствуете, даже медленнее будет, но вот при каких-нибудь 10000 уже будет заметно быстрее.

    Советую попробовать обычные оптимизации, прежде чем браться за преобразование фурье.

    Еще, вместо хранения конца числа в виде особого значения 10 - вам стоит отдельно хранить длину числа в какой-то переменной с говорящим названием (хотя бы len). Тогда код будет сильно читабельнее.
    Ответ написан
    2 комментария
  • Область видимости c Arduino. Как передать define в библиотеку?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что .h файлы просто вставляются в .c файлы, когда вы делаете include.

    Т.е. в файлe, который у вас первым приведен, который делает define 2 и include - MAX_FIELDS будет 2. А в файле library.c, который тоже делает include library.h - MAX_FIELDS уже будет 0.

    Если MAX_FIELDS влияет на декларацию чего-то (например, размер массива в какой-то структуре), то вы получите ошибку на этапе линковки (потому что в разных объектах компиляции будут объявлены разные структуры). Иначе - присваивание MAX_FIELDS 2 в услолвном main.c ни на что не влияет.

    Вам надо задавать MAX_FIELDS в опциях компиляции всего проекта. Обычно это ключ -D, или в Makefile оно его еще можно задать.

    Еще альтернатива - вместо константы MAX_FIELDS передавайте значение в ваши функции, если можете.
    Ответ написан
    3 комментария
  • Python/numpy: как увеличить массив на одну строку без использования дополнительной памяти?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Нет.

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

    Это даже в C++ сделать нельзя, не говоря уже о питоне.

    Edit: Вообще говоря в C++ есть realloc, Но оно не гарантирует расширение существующей области памяти. Ибо она может быть занята чем-то еще.
    Ответ написан
    1 комментарий
  • Как посчитать БЖУ?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Это задача о многомерном рюкзаке (multi-dimensional knapsack). Каких-то простых трюков, как с обычным одномерным рюкзаком тут нет. Только перебор с отсечениями.

    Еще можно свести задачу к целочисленному линейному программированию. Вводите переменные - сколько штук каждого пункта съели, составляете линейные уравнения. Потом можно это все скормить какому-нибудь решателю. Сейчас много библиотек и они довольно быстро такие задачи щелкают. Гуглите "integer linear programming solver".
    Ответ написан
  • Как определить последовательность действий?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Это называется поиск в пространстве состояний. Если бы вы могли построить граф - взять все возможные состояния поля A1 x все возможные состояния поля A2... и провести из каждого ребра, соответствующие всем возможным действиям, то это была бы тупо задача на поиск пути в графе.

    Проблема в том, что состояний очень много. Поэтому граф не генерируется, а строится на лету. А дальше все-равно в этом графе запускается какой-то алгоритм поиска пути. Например A*. Или dfs со всякими эвристическими оптимизациями. Главное это накрутить достаточно оптимизаций, чтобы алгоритм не касался слишком большого количества состояний - потому что все просмотренные состояния надо хранить как-то в памяти.
    Ответ написан
    3 комментария
  • Инициализирование класса?

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

    Если бы в объекте были данные, то первый вариант был бы быстрее всего, потому что он ничего бы не инициализировал, в отличии от остальных.

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

    Третий вариант всегда инициализирует объект и выделяет память, поэтому он будет медленнее.
    Ответ написан
    Комментировать
  • Как узнать, пересекутся векторы?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Введите 2 переменные t и q - это "время" на первом и втором луче, составьте 2 уравнения. Решите их - найдете время пересечения на каждом луче. Убедитесь, что пересечения при t>=0, q>=0:
    x1+t*vx1=x2+q*vx2
    y1+t*vy1=y2+q*vy2


    надо проверить, что оно имеет решение. Преобразуйте его к стандартному виду:
    t*vx1-q*vx2=x2-x1
    t*vy1-q*vy2=y2-y1


    Решите систему методом Краммера. Если определитель системы != 0 - то найдте 2 переменные q и t. Проверьте, что они обе неотрицательные.

    Если определитель равен нулю, то прямые или не пересекаются вообще, или совпадают. Они совпадают, если оба вспомогательные определители системы равны 0.

    В этом случае надо проверить, что лучи пересекаются по отрезку или лучу. Для этого надо проверить, а не лежит ли начало второго луча на первом и наоборот. Для этой проверки можно воспользоватся векторным произведением векторов. Считаете вектор {x2-x1, y2-y1} и умножаете на вектор {vx1, vy1}. Эти 2 вектора или смотрят в одну сторону (и пересечение есть), или в разные. В первом случае векторное произведение будет положительно, во втором - отрицательно. Нулевое произведение считайте как положительное - это значит что или точки совпадают или вектор направления нулевой.

    Т.е. весь алгоритм
    1) Считайте 3 определителя по методу краммера
    2) Если главный определитель не 0, считайте q и t. Пересечение есть, если q>=0 и t>=0.
    3) Если главный определитель 0, но хотя бы один из вспомогательных не 0 - пересечения нет.
    4) Считайте векторное произведение {x2-x1, y2-y1} на {vx1, vy1}. Если оно неотрицательно - пересечение есть.
    5) Считайте векторное произведение {x1-x2, y1-y2} на {vx2, vy2}. Если оно неотрицательно - пересечение есть.
    Ответ написан
    1 комментарий
  • Как передать в функцию указатель если она принимает ссылку?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Никак. Заставьте вашу функцию принимать указатель:

    template <typename type>
      static void readMemory(uintptr_t offset, unsigned int length, type* var) {
        ReadProcessMemory(targetHandle, (LPVOID)offset, var, length * sizeof(type), 0);
      }
    
    uint8_t arr[100500];
    readMemory<uint8_t>(0x00, 10, arr);
    Ответ написан
    2 комментария
  • Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Во-первых, в вашем алгоритме цикл while вообще не нужен. Сколько нужно операций +1, чтобы из a получить a+12345? Ровно 12345. Вам надо просто вычесть одно число из другого.

    Далее, мысль должна быть такая: Вот вы знаете, сколько нужно операций, чтобы все числа в массиве привести к X. Вопрос: сколько операций вам понадобится для приведения всех чисел к X+1? (Подсказка - если число было меньше X, то теперь понадобится на 1 операцию больше. Если число было больше X - то понадобится на 1 операцию меньше).

    Теперь вам надо посмотреть, подумать и выбрать оптимальное X, которому вы будете приводить все числа. Ваш вариант с max/2 не оптимален.
    Ответ написан
    5 комментариев
  • Почему у временного объекта можно вызывать non-const метод?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По поводу вызова неконстантных методов - а с чего вы взяли, что они не дожны быть возможны? Временные объекты не имеют const квалификаторов. Иначе нельзя было бы делать вещи типа SomethingBuilder().WithA().WithB().Finalize().

    //! f6() = X(1);

    Оператор присвоения требует Lvalue слева. Временный объект же - Rvalue. Eго можно ставить только справа от =. А не потому что у него const квалификатор.

    Это сделано скорее всего потому, что, ну, нет же смысла перезаписывать временный объект. Он временный, к нему потом никак не обратиться.

    //! f6().modify();

    Вот тут попытка вызова неконстантного метода у константного (и временного - но это не важно) объекта.

    //! f7(f5());

    Видимо, это чтобы исключить некоторый класс ошибок. Если вы передаете в качестве неконстантной ссылки что либо, значит оно должно внутри менятся и снаружи эти изменения должны быть видны. Иначе можно было бы передавать по константной ссылке или по значению. Но вы передаете туда временный объект - его никак снаружи видно не будет. Он существует только в этой строчке. Поэтому в C++ нельзя инициализировать неконстантные lvalue ссылки через rvalue (временные объекты).
    Ответ написан
    1 комментарий
  • Как прочитать масив данных динамической длинны?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам придется переписать функцию readMemory, чтобы она принималаlength и читала length*sizeof(type). Или вызывайте прямо ReadProcessMemory в вашей функции.

    Текущая реализация для вашей цели не подходит вообще. Тип шаблона должен быть известен на этапе компиляции. А вы хотите как-то в нем передать динамическую длину.
    Ответ написан
    4 комментария
  • С чего начать изучение алгоритмов?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Почитайте Кнут "искусство программирования" а также Кормен "алгоритмы: построение и анализ".
    Ответ написан
    Комментировать
  • Объявлять переменные внутри или перед циклом?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Современным движкам должно быть пофигу.
    Ответ написан
  • Как исправить ошибку сборки проекта, при подключении sdl?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы, похоже, создали обычный оконный проект, а надо было создавать консольное приложение. Легче всего будет пересоздать проект. Внимательно смотрите, что вы там выбираете.
    Ответ написан
  • Геометрическая прогрессия и сложный процент это одно и то же?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Нет. Распишите формулы, они будут разные. В прогрессии каждый раз добавляется степень коэффициента q. В проценте происходит домножение на (1+q):
    A+Aq+Aq^2+Aq^3+...
    A+Aq+(Aq+Aq^2)+(Aq+2*Aq^2+Aq^3)+...
    Ответ написан
    Комментировать
  • Как называется матрица возможных состояний объекта?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    машина состояний?
    Ответ написан
    1 комментарий