Задать вопрос
  • Нужно понять что значит код и что выведется на экран?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Запустите и посмотрите: https://www.onlinegdb.com/online_c++_compiler. Попробуйте поменять по одному символу и смотреть, что происходит с выводом. Так вы поймете, что именно выводится, а потом чуть чуть знания C и вы поймете, почему так происходит.
    Ответ написан
    4 комментария
  • Компилятор сайта не понимает кодировку?

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

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

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

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

    Словарь в питоне, он же ассоциативный массив, действительно, реализован на основе хеш таблицы. Реализован внутри интерпретатора Питон. Это другая структура данных, сделанная на основе массивов и списков (которые реализованы на указателях).

    Но ассоциативный массив можно реализовывать и двоичными деревьями поиска. Например структура set в языке C++ - реализована деревом. Такой ассоциативный массив работает ассимптотически медленнее (логарифм операций вместо константы для поиска/вставки/удаления). Но обладает важным свойством - элементы там упорядочены. Можно найти минимальный ключ, обойти все ключи в порядке возрастания, подсчитать что-то на отрезке ключей. Плюс не нужно придумывать хороший хеш. В хеш-таблицах, если хеш плохой - можно получить O(n) операции. Или может не повести и будет куча коллизий даже для хорошего хеша. В двоичных деревьях поиска (большинстве) гарантирован худший случай за логарифм. В некоторых задачах лучше использовать именно эту структуру, чем хеш-таблицу.

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Только перебор. Или, если подойдёт достаточно хорошее решение - всякие эвристики с жадностями.
    Ответ написан
  • Почему программа может использовать больше динамической памяти, чем выделил `malloc()`?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Вы лезете не в свою память. Программа может упасть, вы можете перетереть значение каких-то других ваших переменных.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Простой файл A.h, сложный B.h.

    B.h включает A.h. Какой-то С.cpp включает и A.h и B.h в любом порядке. Фишка в использовании header-гуардов. Это вот эта штука:
    #ifndef blablabla
    #define blablabla
    
    // определения
    
    #endif // конец файла


    Каждый файл имеет свое уникальное bla-bla-bla (обычно используют имя файла с путем). В таком виде можно без проблем включать любой файл кучу раз и, пока у вас нет циклических зависимостей, сколько угодно сложный проект собирается - надо только помнить всегда включать все, что вы используете.
    Ответ написан
  • Не работает алгоритм std find для строки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы вызываете std::find, который призван искать элемент в коллекции. А пытаетесь искать там строку. Это все почти компилируется, потому что строка - это коллекция символов, по ней можно было бы искать один символ. Но вы передаете туда указатель (ваша строковая константа). Компилятор не может преобразовать его в символ и на это ругается.

    Для того, что вам надо - есть std::string::find. Т.е. вам надо вызвать str.find(" ").

    Или же ищите один символ. Только не забудьте algorithm включить, а то непонятные ошибки с итераторами полезут.
    Ответ написан
    1 комментарий
  • Создание терминального приложения для нескольких платформ?

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Я так понял, проблема именно с глобальными переменными?

    В хедере объявляете переменную как extern, в одном c файле определяете ее с инициализацией без extern - тогда все работает.
    Ответ написан
    Комментировать
  • Это правильная реализация бинарного поиска?

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

    Чтобы работало быстро вам надо не менять lst, а помнить индексы границ текущего куска.

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

    И последнее, в питоне есть операция целочисленного деления - //. Используйте ее вместо приведения к int после деления.
    Ответ написан
    2 комментария
  • Как обрезать двумерный массив в форме прямоугольника?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Посмотрите описание методов slice и map и попробуйте догадаться, что именно делает приведенный вами код.
    Ответ написан
  • Не понимаю, как правильно реализовать программу?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Во-первых, можно отлично читать из файла сразу число. Вы как с консоли числа вводите? Вот точно также, только из файла. Вы как строку-то читаете? Вот передавайте там не строку, а int условный. Ну, еще, если scanf-ом читаете, то надо туда %d вместо %s передавать. А так есть еще функции преобразования числа в строку. Читайте справки по atoi, sscanf, stringstream.
    Ответ написан
    3 комментария
  • Как обрезать путь чтобы осталось только имя файла?

    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".
    Ответ написан