Задать вопрос
  • Как в Си вывести в консоль без записи в буфер?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Можно выводить в stderr через fprintf. Тогда перенаправление в файл запишет туда только то, что выведено в stdout через printf.

    А так /a.out > file.log просто перенаправляет stdout в файл и все, что будет туда выведено, будет записано в файл самой системой. Ваша программа не знает, куда там система будет содержимое потока выводить - в консоль или в файл. Никак на это повлиять вы не сможете. Остается только писать в другой поток, например stderr.
    Ответ написан
  • Какими функциями заменить array_diff() в Си?

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

    Более продвинутый вариант - отсортировать список b и искать там каждый элемент из a бинарным поиском.

    Удобный трюк для удаления элементов из массива - хранить индекс первого не занятого элемента. Тогда получается что-то вроде этого:
    int empty_pos = 0;
    for (int i = 0; i < n; ++i) {
      if (!ShouldDelete(a[i], b)) {
        a[empty_pos++] = a[i];
      }
    }
    n = empty_pos;
    Ответ написан
    3 комментария
  • Как принимать ввод с потока до символа новой строки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    А откуда программа должна знать, что вы не хотели ввести, например
    "1 1 1 2 2 3 3 3 3 3 3 3".

    Почему после четвертой тройки она должна остановиться?

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

    while (std::cin >> value) попытается прочесть число и вернет ссылку на cin, котрая приводится к bool и будет равна false, если произошла ошибка, т.е. прочитать еще одно число не удалось.

    Консоль ждет от пользователя ввод и единственный случай, когда cin не сможет прочесть число, это если закончится входной файл (если запустить программу и перенаправить ввод из файла) или если пользователь введет какой-то символ, который не получится перобразовать в число. Кроме ctrl-z (символ eof) можно, например, ввести символ 'a', поставить точку или еще что-то.
    Ответ написан
    2 комментария
  • Возможно ли полностью покрыть поле паркетом без пересечений?

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

    Покрасьте поле как шахматную доску. Черные и белые клетки. Каждая доминошка будет лежать на двух соседних белой и черной клетках. Постройте граф. Назначьте каждой клетке вершину, а ребра проведите между соседними клетками, если там нет перегородки. Граф - двудольный, ведь черные клетки окружены белыми, а белые - черными. Любое заполнение поля доминошками будет идентично паросочетанию в этом графе и наоборт. Найдите максимальное паросочетание: если оно не полное, то поле покрыть нельзя. Иначе ребра в паросочетании будут местами, куда надо класть доминошки.

    Вот статья с описанием алгоритма и реализацией.

    Это будет решение за O(n^2m^2).

    Другое решение, которое будет быстрее, если одно из измерений очень маленькое, а второе очень большое - динамическое программирование по профилю. Гуглите эти слова. Это сложнее реализовать, но зато будет работать за O(4^n m)

    Edit:
    Alexandroppolus в коментариях предложил использовать Алгоритм Хопкрофта — Карпа для поиска паросочетания, что для данного графа будет быстрее предложенного мной алгоритма Куна и будет работать за O(nm sqrt(nm)) вместо O(n^2 m^2)
    Ответ написан
    7 комментариев
  • Что надо изменить в коде чтобы найти количество максимальных элементов массива?

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Деньги, к сожалению, платят только за работу.
    Не работать по 8 часов в день, однако, есть варианты:
    1) Работать на пол ставки. Но и зарплата будет в 2 раза ниже.
    2) Фриланс. Но тут, опять же, заработок будет пропорционален потраченному времени.
    3) Работать очень много некоторое время, запустить супер успешный гениальный проект, потом не работать, получая прибыль с бизнеса. В среднем может даже быть меньше 8 часов работы в день. Но тут должно очень повезти.
    Ответ написан
    Комментировать
  • Почему при создании динамической строки игнорируется нулевой индекс?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Там же число, которое читается через scanf("%d", &N); в первой строке.
    Ответ написан
  • Как конструктор std::ofstream преобразует std::string в char const * filename?

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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Код в вопросе найдет такое i, что result станет равен 1, если цикл сделать до N. Для любых дельта и гамма. (но там цикл не нужен вообще).

    И наоборот. Какие бы вы дельта и гамма не взяли, может прийти такой Input, что result станет 1, только для очень большого i.

    Во-первых, вам цикл не нужен. Вычисления ваши можно упростить.
    result = (input / delta) / (i / gamma) = input * (gamma / delta) / i

    Если result = 1, то получается i = input * (gamma / delta) (естественно, умножение и деление по модулю N).
    Цикла не надо. Можно сразу вычислить искомое i.
    Решение единственно (если N простое. А если оно не простое, то делить по модулю нельзя).

    И это самое i может оказаться очень большим. Не всегда N-1, потому что у вас ограничение на Input есть дополнительное, Но даже в самом лучшем случае подбора гамма и дельта (обе по 1), вам может прийти input такой, что i будет равно 2^120.

    Ну и, во-вторых, вам не нужны две константы дельта и гамма. Тут есть ровно одна степень свободы - значение gamma / delta. Это должна быть единственная константа в вашем коде. В итоге оно все упрощается до:
    beta = 0x42
    i = beta * input % N
    result = 1


    И вообще тут, очевидно, проблема XY. У вас есть какая-то задача X, вы придумали какую-то фигню, как-то сформулировали вот эту вот задачу в вопросе (У), но вы ошиблись. Решение вот этой фигни в вопросе вам никак не поможет решить вашу изначальную задачу, пототму что вам не хватает знаний (теории групп, например, да и математики в целом). Вы задаете практически бессмысленные вопросы (уже не первый раз). Если хотите, чтобы вам тут действительно помогли - давайте вашу изначальную задачу. Я подозреваю, что это взлом криптографии и вам тут популярно объяснят, что вы зря тратите время.
    Ответ написан
  • Почему мы имеем право решать уравнения методом замены переменной?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Ну, это просто подстановка. Если, как в моем примере, предположить, что z=x^2, то из-за равенства получается и x^2=z. А дальше можно каждый x^2 переписать как z, ведь они равны.

    Или это можно еще понимать как абстрактное мышление. Вот есть у вас уравнение на x. Вы можете заметить какое-то повторяющееся выражение. Оно имеет какое-то значение. Вот это значение можно обозначить новой буквой. Вот вы же можете буквой x обозначить "сколько у вас яблок". Вы точно также можете обозначить буквой z "сколько у вас яблок в квадрате".

    Это можно делать всегда, но в результате этого могут получиться лишние корни. Как например тут, если есть решения с отрицательными z, то никакой x ему не соответствует. Надо аккуратно проверять все значения z и искать соответсвующие им x.

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

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

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

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

    Вам надо, чтобы temp был размером не меньше text.
    Ответ написан
    Комментировать
  • Как вычислить правильно в скрипте python?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Я так понял, надо подобрать константы a,b,c,d?
    Вообще, можно a, b1, c считать равными 1 и менять только d.

    Но у вас там умножение и деление по модулю. Так что все очень сложно.

    Вообще, ваша задача не имеет решения.

    Модуль у вас в вопросе порядка 10^78. А X может быть 10^119-10^120. Если x взять по модулю N, то там может получится вообще любой остаток (потому что 10^120-10^119 = 9*10^119 > N)

    А дальше, умножая эти числа на константу, если N простое (а оно должно быть простым, иначе деление по модулю не определено), то можно получить любой остаток до N. Не только до 2^60 - 2^70.
    Ответ написан
  • Как грамотно переписать фабрику?

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

    В вектор/мап кладите пары stragetyX.GetName(), &stategyX.CreateStrategy
    А дальше находите там нужную строку и вызывайте функцию-фабрику.

    Но вообще, такие штуки c хранением функций-фабрик в контейнере редко делают. Можно в одном месте и иметь вереницу из if-else. Будет не одна длинная строчка на каждый новый класс, а две но покороче.
    Ответ написан
  • Почему не получается передать указатель на вектор в класс?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    void Field(vector <Circle> &circles, vector <Rectangle> &rects) {


    Это передача по ссылке а не через указатель. Сюда надо передавать сам circleArray.

    Но сразу скажу, препод такой подход не примет. Вся идея полиморфизма, наследования и виртальных методов в том, чтобы хранить везде указатели на Figure. А то, что какие-то из них на самом деле Circle, а какие-то Rectangle, это уже детали реализации. Виртуальные методы должны переопределятся в потомках и именно там должна быть логика, специфичная для разных фигур.

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    double circleMainArray[circArraySize] = { centerCoordX, centerCoordY, radius };
    geometry = circleMainArray;


    Тут вы заводите локальную переменную circleMainArray, а потом копируете ее адрес в член geometry. По выходу из конструктора локальная переменная удаляется. На ее месте потом поялвяется что-то другое (она на стеке, так что там могут быть адреса возврата, значения регистров или других локальных переменных).

    Правильно было бы выделять память в куче под geometry и или заполнять его руками, или копировать туда данные из локальной перменной. А еще лучше - использовать std::vector.
    geometry = new double[circArraySize];
    geometry[0] = ...;
    geometry[1] = ...;

    Или лучше
    std::vector<double> geometry;
    ...
    Circle(double centerCoordX, double centerCoordY, double radius) :
       geometry{centerCoordX, centerCoordY, radius} {}
    Ответ написан
    6 комментариев
  • Нужно найти 10 елемент,я так понимаю это прогрессия,совсем не могу разобраться?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно последовательно найти t1, t2, t3 .. t9 и через них циклом подсчитать t10.

    Нужно их хранить в массиве и тупо записать формулу в коде. Знак суммы становится циклом, в котором надо вычисленное через i выражение прибавлять к счетчику.

    Такая реализация подсчета t(n) будет за O(n^2).

    Если подумать, то можно быстрее. Во-первых, при умножении t0 на С, tk умножится на C^(k+1). Можно доказать по индукции. Теперь осталось подсчитать числа для t0=1 и домножить на t0^( n+1).

    Если же выписать числа на бумажке, то можно заметить, что это числа Каталана, которые считаются по формуле
    (2n)!/n!/(n+1)!

    Итого, ответ - (2n)!/n!/(n+1)! * t0^(n+1)
    При n=10 дает 16796.

    Это уже можно подсчитать за O(n).
    Ответ написан
    Комментировать
  • Как реализованы программы записи экрана и стриминга?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Используются системные api. Все полатформо зависимое, к сожалению. На винде можно делать через кучу разных апи: gdi+, dxgi, wgc. Гуглите "слово из списка capture screen".

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

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если просто через >> читать std::string из std::cin, то он будет читать одно слово.
    Чтобы прочитать всю стороку используйте cin.getline.
    Ответ написан
  • Почему не работает функция?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема в том, что код функций из шаблонов генерируется по мере надобности.
    Вот встретил компилятор где-то Test<int> - и начинает создавать функцию для int.
    Но в единице трансляции с Functions.cpp он этого не встретил и ничего не генерирует. А когда он компилирует Source.cpp он может только сгенерировать декларацию, но не определение функции. Ведь он видит хедер, но не что написано в Functions.cpp.

    Поэтому, если весь шаблон определять в .h файле то компилятор сможет сгенерировать что ему надо всегда.

    Второй варинат решения проблемы - в Functions.cpp указать компилятору, что шаблон будет использоватся с такиим-то типами:
    using Test<int>;

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

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