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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    На винде? Кроме gdi+ можно ещё через directx (гуглите dxgi duplicator) или через windows graphics capture api. Но последние 2 не работают в старых системах.

    Если же вам только посмотреть на несколько пикселей, то можно и в gdi+ делать скриншот лишь маленькой части, или вообще ничего не копировать и смотреть на цвет пикселей в экранном DC.
    Ответ написан
    1 комментарий
  • Правильно ли я дал описание для диаграммы?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Нет. В вашу формулу подойдет и верхний треугольник между A и B.
    Ответ написан
  • Как ускорить поиск элементов из статичного string[] по подстроке?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Сначала объедините все ваши строки в одну через какой-то раздилитель, которого не может быть в искомой строке (можно и без него, но с ним код чуть проще будет). В конце поставьте этот же разделитель 2 раза. Вроде "строка1$строка2$строка3$...$строкаN$$".

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

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

    Другой вариант - через преобразование Барроуза — Уилера. Вот есть лекция. Этот алгоритм часто упоминается в курсах по биоинформатике. Реализацию может даже найдете где-то. Потом можно найти номера исходных строк из индексов вхождений через тот же бинпоиск по сортированному массиву индексов начал всех строк в тексте.

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

    Учтите, что построение структуры данных тут будет в несколько раз медленнее простого for+Contains. Выигрыш вы получите, если у вас текст действительно статичный и вы в нем много раз что-то ищите.
    Ответ написан
    7 комментариев
  • Какой тип бинарного дерева используется для Buddy аллокатора?

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

    Его можно вообще без указателей реализовать в массиве. У блока с номером i два ребенка с номерами 2i+1 и 2i+2.

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

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

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

    srand устанавливает состояние генератора псевдослучайных чисел. В качестве seed вы там используете количество миллисекунд, которое целую миллисекунду одинаковое, поэтому состояние генератора у вас в каждой функции rand_offer одно и то же - поэтому числа и генерируются одни и теже. sleep(1) лечит проблему потому, что следующий вызов посчитает другое значение count_ms.
    Ответ написан
    Комментировать
  • Таблица истинности С++. Почему здесь разные результаты?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    ( x == z) || (!x || (y && z)) == 0 означает ( x == z) || ( (!x || (y && z)) == 0 ).
    Приоритет у сравнения выше, чем у ||, которое, по идее, есть лишь часть считаемого выражения. Поэтому у вас полечается не "выражение == 0" а "выражение1" или "выражение2 == 0".
    Возьмите все ваше выражение в скобки и все заработает.

    Во втором куске кода у вас 2 отдельных выражение сравнивается с 0 и скобочки у вас там расставлены правильно.
    Ответ написан
    1 комментарий
  • На сколько сложно создать офлайн генератор иконок?

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

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

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

    Вектора можно перемножать. Скалярное или вектороное произведения. Чаще скалярное ставят на operator*, а векторное на какое-нибудь operator^

    Операторы сравнения обычно делают лексикографически, покомпонентно. Сравнили первое число - у какого вектора больше - тот и больше. Если числа равны, сравниваем вторые компоненты. И т.д. Но это делают редко, потому что смысла вектора сортировать особо нет. Лексикографический порядок пользы особо не приносит.
    Ответ написан
    9 комментариев
  • Как разместить N файлов по папкам?

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

    Если N маленькое, то есть быстрые алгоритмы вроде Динамического Программирования. Но там и перебор будет не то, чтобы сильно медленнее.

    Если вам не важно получить абсолютно минимально возможное количество папок, то подойдет какое-нибудь жадное решение. Оно даст хорошее приближение. Скажем, вместо 30 идеальных папок вы часто получите 40.

    Например, кладите файлы в текущую папку, пока они туда помещаются. Потом создавайте следующую папку. Заполняйте ее, пока размер папки + размер следующего файла <= 2Mb.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    {
      thread gameThread(game_loop, ref(star_pleced), ref(staircase_placed), ref(c), ref(t_placed), ref(r_placed), ref(p_placed), rows, cols, ref(map));
      thread monsterThread(monster_move, ref(map));
      gameThread.join();
      monsterThread.join();
      refresh();
    } while ((c = getch()) != '0');


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

    Потоки тут вообще бесполезны, вы с тем же успехом можете просто вызвать функции напрямую.

    Потоки должны быть запущены один раз и работать в фоне. Тот, который каждую секунду что-то делает, должен внутри содержать цикл и работать бесконечно, на каждой итерации засыпать на 1 секунду.
    Ответ написан
    Комментировать
  • Как исправить ошибку -nan(ind) в С++?

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

    Другая опасность в вашем коде: логарифм отрицательных чисел. Закомментируйте log в вашем выражении, если результат где-то отрицательный - функцию в этом значении x тупо не вычеслить - оно вне области определения.
    Ответ написан
  • Скомпилированный в GCC exe файл вылетает досрочно?

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

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

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    1. #define SPACE ' ' - смысла не несет такая замена. Или какое-то более осмысленное имя, вроде EMPTY_FIELD, или просто в коде используйте ' '. Хотя лучше хорошее имя.

    2. check_field - ужас. Во-первых, проверки на крестики и на нолики идентичны - только сравниваете вы или с 'X' или с 'O'. Ну напишите функцию, которая принимает char и ищет тройку из этих символов. Далее, используйте циклы. 3 строки можно проверить одним и тем же кодом, только индексы сдвигаются на 3 - вот и запустите цикл на 3 итерации. Так же со столбцами. В итоге вместо 8 условий будет только 4.
    Вообще, можно до одного условия в трех вложенных циклах ужать:
    const int dx[4] = {0, 1, 1, 1};
    const int dy[4] = {1, 0, 1, -1};
    for (dir = 0; dir < 4; ++dir) {
      for (int start = 0; start < 9; ++start) {
        int step;
        int x = start % 3;
        int y = start / 3;
        for (step = 0; step < 3; ++step) {
          if (x < 0 || x > 2 || y < 0 || y > 3 || field[x+3*y] != player) break;
          x += dx[dir];
          y += dy[dir];
        }
        if (step == 3) {
          return 1;
        }
      }
    }
    return 0;


    3. print_field тоже делается циклами. Хотя бы по трем строкам.

    4. основной игровой цикл можно делать while (1), ибо по любому из значений check происходит break;
    Ответ написан
    Комментировать
  • Возможна ли гонка данных при отправке их на сокет?

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

    Вот эта часть кода, что по вашему делает? Почему sendto возвращает количество байт, а не код ошибки?

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

    Это связано с тем, что сокеты работают на низком уровне и не гарантируют сохранение порядка отправленных данных. Когда два приложения отправляют данные одновременно, они могут перемешиваться в процессе передачи по сети и приходить в произвольном порядке.


    А это очередная галлюцинация ГПТ. Забудьте эти слова - они не имеют ничего общего с реальностью.

    Попробуйте строки ваши сделать побольше - в пару миллионов символов, вот тут-то вам мешанина и будет приходить.
    Ответ написан
    4 комментария
  • VS Code творит лютую дичь при компиляции и отладке?

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

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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Решите систему линейных уравнений. Обозначьте коэффициенты с1,с2,с3, сложите полиномы, приравняйте коээфициенты пред всеми степенями x к 0. Будет 3 уравнения, 3 неизвестных, но одно из них лишнее (раз они линейно зависимы). Подставьте что угодно ненулевое вместо C, решите первые 2 уравнения относительно A и B.
    Ответ написан
    Комментировать
  • Двойная сумма, непонятно как поменялись предели сумирования?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Что означает вот эта первая надпись с одним знаком суммы? Там же 2 переменные в условии - j и k! Эта надпись означает сумму по всем значениям j и k, т.ч. 1 <= j < k+j <= n. Это множество допустимых значений можно представить как какую-то фигуру на плоскости.
    Ее можно описать вот этими неравенствами, а можно перебрать все допустимые значения j, для каждого из них посмотреть, какие значения k попадают в искомое множество. Вот так и получаются 2 суммы, одна по j, другая по k.
    k не может быть меньше 1 (Видимо, по условию раньше) и больше n, потому что иначе k+j превзойдет n. Зафиксировав k, остаются 2 условия 1 <= j и k+j <= n. ведь j < k+j всегда. Из этих двух условий получаем границы суммирования на j.
    Ответ написан
    Комментировать
  • Почему возникает ошибка Fatal error. System.Runtime.InteropServices.SEHException?

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

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

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

    Судя по сигнатурам функции, возможно вы пустой массив туда передаете вместо чего то осмысленного.
    Ответ написан
    7 комментариев
  • Как сделать ввод через стандартный поток (stdin) и через файл?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Есть такая функция freopen. Можно всегда читать через scanf, read из stdin, но если указано имя файла, то переоткрыть stdin на файл:
    freopen("input.txt", "rb", stdin);
    Ответ написан