Задать вопрос
  • Как Исправить код?

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

    Можно делать так вместо ZeroMemory:
    STARTUPINFO info={sizeof(info)};
    Ответ написан
  • Как удалить запись из структуры?

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

    Для удаления надо пройтись по всему списку - это уже делается в функции main при выводе библиотеки (кстати, там не нужен pLibrary. Можно совместить цикл while и цикл for после него. Вы проходитесь циклом по элементам списка, кладете их в массив и потом проходитесь по массиву. Достаточно просто делать с ними, что вам надо прямо в первом цикле).

    Потом, вместо вывода сравнивайте название текущей книги с введенным с клавиатуры (функция strcmp). Если совпало, то надо предыдущему элементу в next присвоить next текущей записи и потом вызвать free() от текущей записи и вывалиться из цикла через break.

    Да, единственная сложность - надо поддерживать указатель на предыдущую запись, а лучше даже на next у предыдущей записи (это будет LIBRARY**). Тогда для удаления надо просто head->next записать туда и текущий элемент выпадет из списка. Перед переходом к следующему элементу в цикле while просто перезапишите этот указатель на &head->next. Изначально он должен быть &head. Таким образом можно удалить даже первый элемент списка без разбора случаев.
    Ответ написан
  • Как вычислить количество слов, которые начинаются с большой буквы, подобное этому коду?

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

    Вам могут понадобится функции isalpha() isspace() isupper() из файла ctype.h
    Ответ написан
    Комментировать
  • Какой алгоритм сортировки односвязного списка?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Диагональ, которая идет слева сверзу вниз вправо - это j == i. Вторая диагональ - это j == n-1-i.

    Соответственно, штриховка это когда j лежит между n-1-i и i включительно. Надо оба знака развернуть. Только сначала замените < N... на <= N-1...
    Ответ написан
    Комментировать
  • Как сделать реверс масива на С++?

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

    void Reverse (int *a, int x, int y) { 
      int i = y+1;
      int j = x-1;
      while (i < j) {
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
        i++;
        j--;
      }
    }


    Или, если хочется, можно покороче:
    for (int i=x+1, j = y-1; i < j; i++, j--) {
      std::swap(a[i], a[j]);
    }


    Или совсем просто, если это не задание а для дела нужно:
    std::reverse( &a[x+1], &a[y]);

    Только надо обязательно проверить, что x < y - что есть что разворачивать.
    Ответ написан
    1 комментарий
  • Как можно найти все пути между вершинами графа networkx?

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

    Готового решения нет, потому что это довольно редкая задача - получить все пути. Кстати, даже без самопересечений путей может быть экспоненциально много. Уже для для 15 вершин есть тривиальный граф, в котором почти 100 миллиардов простых путей между любыми двумя вeршинами.

    Если вам надо перебрать пути, чтобы выбрать из них лучший, или собрать комбинацию (допустим, k не пересекающихся параллельных путей или несколько кратчайших путей), то почти наверняка есть более быстрые алгоритмы, чем перебор всех путей. Напишите вашу задачу - вам подскажут.

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

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

    def dfs(v, end, graph, path, visited):
      if v == end:
        print(path)
        return
      for u in graph.neighbours(v):
        if u not in visited:
          path.append(u);
          visited.add(u);
          dfs(u, end, graph, path, visited)
          path.pop();
          visited.remove(u);
    
    // вызывать dfs(start, end, graph, [], set())
    Ответ написан
    Комментировать
  • Как из циклического сдвига вправо сделать циклический сдвиг влево?

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

    Вариант чуть получше - вместо разворота, представить, что массив развернут. Тогда при любом обращении к элементу номер x надо обращаться к элементу n-1-x. Т.е. тупо в программе, где сдвиг делается(после ввода), каждый arr[x] заменить на arr[n-1-x] (примеры x у вас там - n-1, i+1, i, 0).

    Вариант еще лучше - включить голову и просто подумать. Сдвиг влево - это в сторону уменьшения индекса. arr[0] становится arr[1], arr[1] - arr[2], и так далее. arr[n-1] становится arr[0]. Т.е. надо в буфер запомнить arr[0], пройтись циклом по возрастанию i и присвоить каждому элементу следующее за ним (+1 к индексу) значение. Потом arr[n-1] заполнить из буфера. На самом деле получится то же, что и в предыдущем варианте, но без лишних вычислений индексов.

    Вариант совсем хороший - не городить shift сдвигов на одну позицию, а сдвигать сразу на shift позиций. Для этого в буфер надо засунуть первые shift элементов, потом пройтись циклом и записывать в i-ый значение из i+shift-ого. Потом последние shift позиций заполнить из буфера.

    Вариант со звездочкой - можно делать без буфера на shift элементов, и сдвигать на shift позиций прямо в массиве, но тут надо знать про перестановки и GCD.
    Ответ написан
    6 комментариев
  • Как найти угол для поворота вектора?

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

    Достаточно только иместь координаты обоих векторов (синего и фиолетового) в евклидовом пространстве.

    Делаете произведения, делите длину вектора или число на длины изначальных векотров и получаете синус и косинус. Этого уже достаточно для матрицы поворота. Но если вам нужен сам угол, то скормите эти значения функции atan. На знаю C#, но точно должна быть версия, которая получает значения синуса и косинуса.
    Ответ написан
  • Что не так с кодом для решения по математической игре Баше?

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

    Во-вторых, ошибка в алгоритме. Задача - проверить, что шаги оптимальные. Для этого вам надо знать оптимальный шаг и сравнивать его с текущим. Можете сформулировать оптимальную стратегию?

    Возьмите, например, k=4,5,6 и порисуйте на бумажке, попробуйте подсчитать, какие позиции выигрышные (из них можно сделать ход в проигрышную позицию), а какие - проигрышные (любой ход ведет в выигрышную позицию). Считайте увеличивая количество предметов. Позиция с 0 предментами - проигрышная - предыдущий игрок придя в нее выиграл. Позиция 1 - выигрышная, потому что можно пойти в проигрышную 0. Найдите закономерность, попытайтесь ее логически обосновать.

    Пример для k=3:

    0 - проигрышная

    1 - выигрышная ( можно взять 1)

    2 - выигрышная (можно взять 2)

    3 - выигрышная (можно взять 3)

    4 - проигрышная

    5 - выигрышная (можно попасть в 4, взяв 1)

    6 - выигрышная (можно попасть в 4, взяв 2)

    7 - выигрышная (можно взять 3 и попасть в проигрышную 4)

    8 - проигрышная (любой ход ведеть в выигрышные 5-7)

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Звучит, как бинарный поиск. Изначальный шаг - половина длины массива (128).
    Следующий, половина от этого и так далее. Так будет максимум 8 проверок всего.

    Если же надо делать обязательно +1 вторым шагом, то можно вычислить максимальное количество проверок, если первый шаг - X, а длина массива - N.

    Первых проверок будет максимум - floor(N/X), вторых (с шагом +1) - X-1.

    Можно примерно подсчитать в вещественных числах и попытаться минимизировать f(x) = N/X+X.

    Можно найти производную f'(x) = 1-n/x^2. Ноль у этой производной при x=sqrt(n).

    Отсюда получается, что примерно sqrt(256)=16 - искомая длина. Максимальное число проверок - 32.
    Ответ написан
    3 комментария
  • Кто и когда использует бинарные деревья и другие структуры данных?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Есть такая штука: https://chromium.googlesource.com/infra/goma/server/

    Позволяет собирать большие проекты параллельно на куче машин. Да, эти 30 минут сборки все равно придется потратить. И никто вам бесплатно вычислительные мощности под это не даст. Придется свои сервера настраивать.

    Еще есть вариант переструктурировать ваш проект, что бы при небольших изменениях понадобилось бы собирать лишь малую часть объектников. И 2 гигабайта в одном файле - это какой-то перебор. Если вы тесты разобъете на много логически обособленных частей, то есть шанс, что сборка сильно ускорится. Да, придется запускать больше файлов, но это сделать просто.
    Ответ написан
    Комментировать
  • Почему инициализация целочисленного указателя 0 или NULL не вызывает предупреждений, хотя 0 - это целочисленная константа?

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

    Но 0 - исключение. Потому что нулем принято обозначать пустой, ни на что не указывающий указатель. Обычно для этого в C используют NULL, чтобы разделять число 0 и пустой указатель в коде. Но NULL, фактически и есть 0.

    Компилятор ничего не приводит, а просто игнорирует присвоение 0, ибо это нормальная ситуация.
    Ответ написан
    1 комментарий
  • Как я могу использовать объект JavaScript в c++?

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

    Если же вы хотите эту конкретную (msg) структуру парсить, то возможно вам удасться превратить json в class в двумя string и одним int.
    Ответ написан
    Комментировать
  • Как найти рекурсивным способом эйлеров путь в графе, из какой вершины начинать?

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

    Эйлеров путь существует от вершины с выходной степенью на 1 больше входной степени до вершины у которой входная степень на 1 больше, чем выходная. (Если граф неориентированный, то путь от одной нечетной вершины до другой). При этом все остальные вершины должны быть сбалансированны.

    Это элементарно доказать - путь в каждую вершину входит сколько-то раз и столько же раз выходит. Исключение - только начальная и конечная вершина, если они не совпадают.

    Соответственно, вам надо подсчитать степени всех вершин, проверить что все хорошо (максимум одна с in==out+1 и одна с in==out-1) и запустить или от любой или от той, у которой исходящих ребер больше.
    Ответ написан
    Комментировать
  • Как замерить частоты тактов, отводимых на операцию в C?

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

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

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

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

    Если итератору присвоить значение (it = 10;), то оно остается в памяти, при сдвигании итератора вперед (it++;) это значение записывается в выходной файл и следующее присвоение скормит итертору значение в следующей позиции. Этот итератор сделан, чтобы можно было писать в файл, как в C++ коллекцию (например, в вектор).

    Важно, что у этого итератора оператор * ничего не делает, возвращает сам итератор. Оператор присвоения, кстати, тоже возвращает сам итератор.

    Поэтому конструкция *(val%2 ? OddOut : EvenOut) вернет или итератор OddOut или EvenOut в зависимости от четности val. Далее, конструкция (... = val)++; запишет число val в один из выходных итераторов и сдвинет его на позицию вперед.

    Весь код выше создает 2 output_iterator, для двух заданных файлов. Потом for_each через оператор() у класса скармливает ему входные числа из cin (тут работает istream_iterator, который позволяет читать из файлов, как из вектора). А класс, пользуясь конструкцией выше, записывает числа в один из двух файлов в зависимости от четности.
    Ответ написан
    Комментировать
  • Как Вы обходитесь без "if"?

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    if (res1 = true)

    Тут вы присваиваете переменной res1 значение true и потом смотрите на ее значение в условии.

    Это вызвано тем, что оператор присврения возвращает значение переменной. Т.е. (res1 = true) == true. Если это вставить в if, то это то же самое что if(true).

    Для сравнения нужно использовать "==".

    Но, вообще говоря, if(res1 == true) - очень плохой код. Правильно писать if (res1).
    Ответ написан
    Комментировать