• Как вернуть несколько значений из функции?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Кроме параметров функции, можно возвращать структуру с именованными значениями или std::vector или std::touple.
    Ответ написан
    6 комментариев
  • Что за ошибка во время вывода?

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

    У вас опять куча мелких ошибок в коде.

    На вскидку:
    f надо уменьшать там, где у вас закомментированно, после ввода. А то вы после основного цикла обращаетесь по индексу не уменьшенного f и выходите за границу массива.

    Массив p надо переписывать только при удачной релаксации, вы же в основном цикле, после вызова функции еще зачем-то всегда переписываете предка. Из-за этого у вас там полный бред в массиве ссылок к предку получается и цикл вывода, скорее всего, виснет в бесконечном цикле из ссылок.
    Ответ написан
  • Как не обрезать стркоу после \0?

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

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

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

    Похоже, что первые index позиций в массиве arr считаются зафиксированными.
    Тогда вам надо ставить на следующее место все оставшиеся числа по порядку и рекурсивно запускаться дальше.

    Но ваш подход со swap-ами первого не зафиксированного числа со всеми остальными перемешивает эти оставшиеся числа. Если вы пройдетесь по вашему решению отладчиком или будете выводить arr в начале функции всегда, то вы заметите, что там числа после index идут не по порядку. И ваш алгоритм, беря их индесы по порядку, может сначала поробовать не самое маленькое число.

    Вам надо добиться того, что оставшиеся в arr числа после index всегда шли по порядку на момент рекурсивного вызова.

    Пусть ставшиеся числа 1,2,3,4. Сначала вы ставите на первую позицию 1 (оставляете все как есть).
    Потом вы должны получить в массиве 2,1,3,4 и запуститься рекурсивно. Это один swap.
    Потом надо получить в массиве 3,1,2,4. Это можно сделать одним swap из предыдущего состояния.
    Важно тут, что вы не возвращаете массив назад после каждого рекурсивного вызова. Иначе вам пришлось бы делать циклический сдвиг части массива на каждой итерации (1,2,3,4 -> 3,1,2,4).

    В конце, после последнего рекурсивного вызова у вас будет 4,1,2,3. Чтобы вернуть все как было вам придется после цикла с рекурсивными вызовами сделать циклический сдвиг массива влево на 1 позицию.

    Т.е. рекурсивные вызовы будут как-то так:
    perm( arr, size, index + 1 );
    for( i = index + 1; i < size; i++ )
    {
        swap( arr[i], arr[index] );
        perm( arr, size, index + 1 );
    }
    int tmp = arr[index];
    for (i = index; i < size-1; i++)
        arr[i] = arr[i+1];
    arr[size-1] = tmp;
    Ответ написан
  • Почему возникает ошибка 'std::out_of_range'?

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

    Скорее всего, это происходит на строчке:
    result = num.at(0);
    Ответ написан
    Комментировать
  • А как предков вывести?

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

    В очередь вы должны класть только идентификатор вершины/состояния. В той задаче это были 2 координаты клетки поля. Тут - это четырехзначное число.

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

    Еще раз, в очереди у вас только число, а в массиве рядом пометки о песещении и путь к предку (расстояние конкретно в этой задаче считать и выводить не нужно).

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

    В конце надо циклом while от конечной вершины по сохраненным предкам идти, пока не упретесь в начало. Потом список обойденных чисел надо развернуть. Или хитрость - проводите обратные операции начиная с конечного состояния, пока не найдете начальное. Операции развернуть просто - вычитайте из первой цифры и прибавляйте к последней. Сдвиги симметричны и остаются как есть. Тогда не надо разворачивать ответ после восстановления циклом while.
    Ответ написан
    Комментировать
  • А конь по кругу ходит?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Что-то не то с bfs. Вместо set visited надо иметь двумерный массив, в котором надо считать расстояния. Значение оттуда же и возвращать. Еще плохой код в том что локальные x1, y1 имеют те же имена, что и аргументы функции.
    Ответ написан
  • Почему в С++ появляется Segmentation fault?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    q.push(make_pair(x,y));
    // или эффективнее.
    q.emplace(x,y);
    Ответ написан
    3 комментария
  • Как правильно решить задачу, используя формулу комбинаторики?

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

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

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Обычно можно, но с оговорками. Csv может быть урезан. Например там только текст, а оригинальный формат ещё и шрифт размечал.

    Но эти потерянные вещи можно придумывать по ходу на какие-то стандартные значения.

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема с win api: https://learn.microsoft.com/en-us/windows/win32/in...

    Оно ожидает вот такие коды. И, если для заглавных английских букв оно еще совпадает с кодами ascii, то для строчных букв - нет.
    Ответ написан
  • Как считать длинные числа в Python?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    В питоне большие целые числа встроенные. Но только целые.
    Если вы хотите соранить всю точность, то вам нельзя использовать числа с плавающей точкой. В вашем коде у вас деление на 100, которое и приводит к преобразованию в float и потерю точности. Замените деление на целочисленное и ответ будет точным.

    i - i * p // 100 посчитает точно, но там окргуление при делении будет вниз. Чтобы округлить вверх, можно воспользоваться хитростью - прибавть в числитель знаменатель -1: (i * p + 99) // 100 округлит вверх.
    Ответ написан
    Комментировать
  • Ошибка unresolved external symbol с конструктором/деструктором в классе?

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

    Или пользуйтесь системой сборки (cmake, visual studio, ninja, и т.д...) или вручную запускайте 3 команды: сделать объектник из main.cpp, сдлеать объектник из EcsSystems.cpp, собрать из объектников исполняемый файл.
    Ответ написан
    Комментировать
  • Обход Dom дерева как то относится к дискретной математике?

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

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

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

    Умное и быстрое решение, к сожалению, будет сложно написать без std::unordered_map. Такое решение будет работать за O(n). Самостоятельно хеш таблицу писать будет сложно. Но если без хеш таблицы, то решение будет работать также медленно, как и тупое рекурсивное прикладывание, поэтому приведу тут все решение.

    Основная идея - надо классифицировать все вершины по форме их поддеревьев. Назначить каждой форме номер. Потом остается только найти вершины с тем же номером, что и корень второго дерева.

    Для нумерации форм надо рекурсивно получить номера для двух детей и потом проверить, а встречали ли вы раньше вершину с двумя такими детьми. Если да - то вы знаете ее номер. Если нет - то назначьте новый номер. Вот тут и нужена хеш таблица, она же unordered_map.

    Пустые вершины всегда имеют какой-то номер, допустим, 0.

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

    void Match(Tree *stack, Tree *needle) {
      std::unordered_map<std::pair<int, int>, int> shapes;
      int needle_shape = ClassifyShape(needle, shapes, -1);
      ClassifyShape(stack, shapes, needle_shape);
    }
    
    int ClassifyShape(Tree *tree, std::unordered_map<std::pair<int, int>, int> &shape, int find_shape) {
      if(!tree) return 0;
      int l = ClassifyShape(tree->left);
      int r = ClassifyShape(tree->right);
      auto pat = make_pair(l, r);
      auto it =  shapes.find(pat);
      int this_shape = -1;
      if (it == shapes.end()) {
        this_shape = shapes.size();
        shapes[pat] = this_shape;
      } else {
        this_shape =  it->second;
      }
      if (this_shape == find_shape) {
        std::cout << "Found match at node " << tree->value << std::endl;
      }
      return this_shape;
    }


    В нивном решении надо заменить unordered_map shapes на массив пар чисел (или массив структур или два массива чисел). Циклом в нем проищите текущую пару l, r, если не нашли, то допишите в конец.

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

    Но, возможно вашему преподу такое будет слишком заумно. Тогда вам нужна аккуратная рекурсивная функция сравнения:
    bool Compare(Tree* a, Tree *b) {
      if (a->left && !b->left) return false;
      if (a->right && !b->right) return false;
      return (!a->left || Compare(a->left, b->left)) && (!a->right || Compare(a->right, b->right));
    }


    Тут все просто. Если у корней разная конфигурация детей, то деревья точно не совпали. А дальше надо чтобы рекурсивно совпали поддеревья в левых и правых детях.

    А дальше вам надо рекурсивно пройтись по первому дереву и вызвать вот эту Compare для текущей вершины и корня второго дерева. Если совпало - то выводите текущую вершину.
    Ответ написан
  • Массив. выделение памяти. ошибка сегментирования. но почему?

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

    Проблема ошибок работы с памтью, что результат непредсказуем. Программа может упасть во время попытки что-то не то сделать с массивом, отработать неправильно, вывести неверный ответ в конце, упасть при завершении программы. Это зависит от тысячи факторов: что как компилятор расположил в машинном коде, как он решил использовать регистры... Поэтому даже перестановка слагаемых местами может влиять на результат в неправильной программе. Это и есть тот самый знаменитый Undefined Behavior.

    В вашем случае arr[i] + abs(min), очевидно, может запрасто выйти за границы 0.. temp_arr_length-1.
    Ответ написан
    Комментировать