Задать вопрос
  • В чем разница связаного списка от хеш-таблицы?

    @Mercury13
    Программист на «си с крестами» и не только
    Связанный список решает такую задачу: как хранить коллекцию объектов, добавляя и удаляя туда объекты. (Простите, что я не пишу характеристики того и другого, почитайте это в умных книгах)

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

    Хэш-таблица решает другую задачу: наладить отображение ключ→значение. Например, «осёл → иа, петух → кукареку», и так далее. Массив, только индексом будет не цифра, а что-то другое: x[«осёл»] = «иа». Так называемый ассоциативный массив.

    Если индексом массива может быть только цифра, поступим так: превратим нашего осла в цифру — например, о+с+ё+л = 4363 (в Юникоде), и пусть 63 — это номер гнезда. В 63-м элементе массива пусть и лежит наше «осёл → иа».

    Если у другого животного значением хэша будет 63 — это хэш-коллизия, и в разных реализациях решается по-разному. Я знаю такое: в гнезде лежит не просто один элемент, но связанный список. Главное, что такое слегка снижает производительность, но допустимо.
    Ответ написан
    Комментировать
  • Почему возникает конфликт MAC адресов?

    @Mercury13
    Программист на «си с крестами» и не только
    MAC-адрес принадлежит LG Electronics. Вероятно, на «янчуде» MAC-адрес был скопирован с ноутбука LG, а потом сам этот ноутбук подключился к этой сети.
    Ответ написан
    2 комментария
  • Каков смысл скалярного произведения в Cel Shading?

    @Mercury13
    Программист на «си с крестами» и не только
    Отвечу по существу.

    У нормали длина всегда 1. Иногда это реально вектор, перпендикулярный к полигону — если мы хотим осветить плоский полигон как плоскость. Иногда мы хотим из плоских полигонов создать впечатление криволинейной поверхности и потому делаем (например, интерполяцией или специальной текстурой, т.н. картой нормалей) непрерывное поле нормалей.

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

    Если длина вектора луча тоже 1 — то результат будет [−1…1]. Если он меньше 0 (в случае, если нормаль наружная, а луч идёт от источника света) — перед нами коэффициент, во сколько раз реальная освещённость меньше, чем обеспечиваемая источником света. Если больше — поверхность в собственной тени. (Расчёт падающих теней — отдельный и сложный вопрос.)

    С цел-шейдингом никак это не связано, это вообще база по освещению.
    Ответ написан
    Комментировать
  • SwapBuffers/ glXSwapBuffers потребляет ровно 50% времени работы приложения(нагрузка неважна),в чём может быть причина?

    @Mercury13
    Программист на «си с крестами» и не только
    glSwapBuffers крутится в ожидании VSYNC’а. Потому и потребляет столько.
    Ответ написан
  • Как прочесть аргументы функции на стеке / заставить gcc хранить аргументы функции на стеке?

    @Mercury13
    Программист на «си с крестами» и не только
    https://godbolt.org/z/ARYhis
    Если посмотреть в пролог функции, она делает локальную копию нашей a. А желаемое место в стеке на 36 байтов выше, чем вы ищете.
    Разумеется, всё под x86. Вызов под x64 подразумевает регистры.

    UPD. А вот Интел не делает локальных копий и всё на месте.
    Ответ написан
    Комментировать
  • Есть ли функция которая сильно меняет большие значения и чуть чуть маленькие?

    @Mercury13
    Программист на «си с крестами» и не только
    Главное требование: f’(0)=1. Но из вашего описания непонятно, как функция должна вести себя на ∞-и, и вот несколько вариантов.

    Самое простое — это линейная функция kx, k<1 (например, 0,9x). Она везде (и на ∞-и) линейна.
    Можно посложнее: x/(kx²+1). Этот зверь будет переть к нулю.
    Можно что-то среднее: k·ln(x/k + 1). Стремится к ∞-и, но не так, как x.
    Ещё вариант: 2k sqrt(x/k + 1). Тоже стремится к ∞-и, но побыстрее.
    Если нужно к константе a — то [2a/pi] arctg(x/a). Единственное что — для управления скоростью сходимости придётся в арктангенс вместо x подставить примерно такую же функцию (f'(0)=1).
    Ответ написан
  • Как понять условие задачи?

    @Mercury13
    Программист на «си с крестами» и не только
    Подобный вывод используется, чтобы было понятно, что вы способны, если нужно, вычислить с точностью до обыкновенной дроби, но в длинную арифметику (а дроби бывают длинные) не лезть. Ибо реализации длинной арифметики различаются по эффективности от ЯП к ЯП, а в некоторых вообще нет штатной (внешние библиотеки в олимпиадном программировании запрещены).

    Числа P и Q высчитываем с точностью до остатка от деления на Z := 109+ 7.

    Авторы обещают, что Q mod Z ≠ 0. Z — простое. Тогда НОД(Q mod Z, Z) = 1. Так называемый расширенный алгоритм Евклида (гуглите!) позволяет подобрать такие числа, чтобы m(Q mod Z) + nZ = 1.

    Ваша задача — вывести ((P mod Z) · m) mod Z. Специально указал дважды mod Z: первое у вас будет при работе с числом P, второе — при генерации вывода.

    Почему так? Возьмём вместо здоровенного Z цифру поменьше, 17. Если у вас получился результат 100/400, при расчётах выйдет цифра 15/9, и 9·2+17·(−1) = 1, и ваша задача — вывести (15·2) mod 17 = 13.

    Если же у вас получилось, например, 35/140, при расчётах получается 1/4, 1·(−4)+17·1 = 1, и вы должны вывести (1·(−4)) mod 17 = 13. То есть: независимо от того, насколько сократимая дробь у вас получилась, вы получите один и тот же результат. Тут надо уточнить: там, где возможен отрицательный числитель, нужен не обычный % из Си++, а (a % Z; если получилось отрицательное — добавь Z).

    Ну а арифметических переполнений просто не допускайте, Z = 109 + 7 позволяет умножать в типе long long и не уходить в переполнение.

    UPD. То, что Z — простое, даёт несколько выгод. Часто результат бывает круглый, и простота требует честно считать остаток, а не угадывать. Ну и побочек меньше.
    Ответ написан
    3 комментария
  • Почему шарик застревает в стене?

    @Mercury13
    Программист на «си с крестами» и не только
    У вас тут переменная кадровая частота. Если за длинный кадр шарик ушёл далеко за стенку, короткий кадр его не сможет вытащить наружу и снова инвертирует скорость — шар застрял. (Я это с лёгкостью повторил функцией Windows 10 «Aero Shake»).

    В простейшем случае — определять, за какую стенку шар выскочил, и давать ему скорость такую, чтобы он возвращался в площадку. А не просто vx=−vx, независимо от того, куда эта скорость смотрит.

    Также стоит ограничивать длительность кадра, и если он, например, продлился больше 0,2 с — пусть игра в такой ситуации «запнётся». Случилось что-то нехорошее, и не хочется, чтобы всё слетело с катушек со своих позиций.

    Также надо давать float time = clock.restart().asMicroseconds(); Сейчас компы быстры и погрешность незначительна, но всё-таки.
    Ответ написан
    Комментировать
  • Ошибка при чтении из файла в си.Что делать?

    @Mercury13
    Программист на «си с крестами» и не только
    feof возвращает true, когда мы попытались прочитать и не смогли, потому что каретка ударилась в конец файла. А не когда каретка аккуратно припарковалась в конце файла — и уж тем более не когда она отделена от конца пробелами.

    Лучше прочитайте про scanf…
    On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.

    …и посмотрите, как можно переделать условие цикла.
    Ответ написан
    Комментировать
  • Не работает функция. Что сделать?

    @Mercury13
    Программист на «си с крестами» и не только
    Я пока вижу…
    shitf_up(s,Parent);

    Может, ещё вы напутали с порядком кучи, но на таком кусочке кода этого не видно.
    Ответ написан
  • Почему "идентификатор не определён"?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Вытащи p, p1, p2 наружу из if. Читай «область видимости».

    2. Я бы сделал так…
    Work* p = NULL;
    if () {
      p = new Work();
    }
    delete p;

    Работает, потому что NULL можно спокойно уничтожать, и ничего не будет.

    На Си++11 можно также использовать умные указатели.
    std::unique_ptr<Work> p;
    if () {
      p = std::make_unique<Work>();  // простите, это Си++14, на 11 чуть не так.
    }
    Ответ написан
    Комментировать
  • Qt + MinGW + LTO + LLD: как заставить их работать вместе?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    К сожалению, я прошу невозможное. И связано это с архитектурой оптимизации при линковке GCC. Дело в том, что сам LD вызывает оптимизатор, и очень, блин, жаль. Ведь у LLVM другое устройство виртуальной машины, которая делает оптимизацию при линковке.
    Ответ написан
    Комментировать
  • Сhar *dictionary[][] = {}; Зачем тут const?

    @Mercury13
    Программист на «си с крестами» и не только
    Итак. Да, строковый литерал — это const char[], преобразуемое в const char*.
    • Си++03 разрешал (но не одобрял).
    • Си++11 запрещает.
    • Одинаковые строковые литералы компилятор может преобразовать в один адрес, а также хранить в памяти, куда писать нельзя — потому const. И в Си без крестов тоже, только там попытка записи даст простой AV.
    • Const — это т.н. «cv-модификатор» (const-volatile), входит в систему типов Си++, устанавливается свободно, снимается операцией const_cast и означает, что объект нельзя изменять.
    Ответ написан
  • В чем ошибка?Обьясните в чем ошибка?

    @Mercury13
    Программист на «си с крестами» и не только
    Вместо знака умножения плюс стоит.
    beforeTax = tirePrice + numTires;

    .07 — это очень некузявая запись для 0.07, ставки налога. Знаете же, что в США налоги зависят от кучи параметров, и их надо прибавлять вручную.
    Ответ написан
    Комментировать
  • Как изучать С# после С++, и стоит ли вообще?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы просто изучаете Си с диезом, и всё, что узнаёте по этому языку, прикладываете к вашим знаниям Си с крестами.

    > С++, С# или все вместе?
    По минимуму желательно освоить оба языка, а вот рисунок кода, инструментарий и прочее — по Си# подтянуть хвосты будет как-то проще.

    > Если С# то учить с нуля?
    Вы уже не ноль, и курс, где вас будут просить решить квадратное уравнение в консоли, может поначалу для вас оказаться тратой времени. Но это уже зависит от ваших знаний — видимо, у вас их не так много и потери будут невелики.

    > Если С++, то что учить дальше кроме ООП?
    Строить живые проекты. Qt (хоть в простейшем виде). SDL (хоть в простейшем виде, раз уж вы геймдевщик). Какой-нибудь игровой движок (Unreal или Godot), но это уже серьёзно.

    > Есть ли что-то что повысит мои шансы попасть в геймдев?
    Трёхмерная математика. Кватернион единичной длины как замена матрице поворота в 3D. Обработка изображений и звука, хоть простейшая. «Programmer’s art» вроде шейдеров и систем частиц. Умение программировать трёхмерные игры на готовом движке хоть в простейшем варианте. Умение написать своими силами (на тонкой обёртке вроде SDL) хотя бы «Элиту».
    Ответ написан
    Комментировать
  • Есть ли в для C++14 map с поддержкой constexpr хэша?

    @Mercury13
    Программист на «си с крестами» и не только
    Нет, разумеется. ООП подразумевает смену состояния объекта, а в константных выражениях смена состояния запрещена. Может, и можно какую-то собственную горбушку придумать, но не знаю, как (даже конструктор — смена состояния).

    Если же задача — посчитать при компиляции хэш для константного элемента, и всё… вот это интересно, но тоже не знаю, как реализовать.
    Ответ написан
  • Задача по олимпиаде?

    @Mercury13
    Программист на «си с крестами» и не только
    ОПРЕДЕЛЕНИЕ. Беспорядок — а) чёрный блин внизу; б) белый блин на чёрном, чёрный на белом.

    ТЕОРЕМА. Переворот исправляет не более одного беспорядка.
    ДОКАЗАТЕЛЬСТВО. Ни в переворачиваемой стопке, ни в оставшейся как был беспорядок, так и остаётся. У нас есть шанс исправить один беспорядок — тот, в который мы залезли лопатой.

    СЛЕДСТВИЕ. Оценка снизу — количество беспорядков.

    ТЕОРЕМА. Эта граница достижима.
    БАЗА ИНДУКЦИИ. У нас 0 беспорядков. Все блины белые — реально нужно 0 ходов.
    ШАГ ИНДУКЦИИ. Доказано, что граница достижима для 0…N−1 беспорядков. Пусть теперь беспорядков N.
    Если количество беспорядков нечётно, вверху будет чёрный блин. Перевернём всю стопку, кроме нижних белых блинов. Теряем одним ходом один беспорядок, а для N−1 граница достижима.
    Если количество беспорядков чётно, вверху белый блин. Поскольку беспорядков не 0, белые блины лежат на чёрных. Перевернём белую группу (теряем один беспорядок) и получаем вверху чёрный блин. Теряем одним ходом один беспорядок, а для N−1 граница достижима.

    АЛГОРИТМ. Подсчитать количество беспорядков в стопке, вывести его. O(N).
    Ответ написан
    Комментировать
  • Какой парсер для математических выражений на Qt посоветуете?

    @Mercury13
    Программист на «си с крестами» и не только
    Egorithm, Отлично, теперь у вас есть файл библиотеки *.a, include-файлы *.h и разделяемая библиотека *.so.
    Задачи, в порядке приоритета.
    1. Заставить прогу компилироваться, для этого надо в проекте прописать доступ к include-файлам *.h.
    2. Заставить прогу линковаться, для этого надо в проекте прописать доступ к *.a (-lmuparser -L$$PWD).
    3. Заставить прогу запускаться, закинув куда надо *.so.
    Ответ написан
    1 комментарий
  • Как ускорить функцию?

    @Mercury13
    Программист на «си с крестами» и не только
    Название, конечно, не по прогерскому фэншую, и вспоминается знаменитый стих столетней давности:
    «We slog, slog, slog, slogging over Africa,
    Boots, boots, boots, boots moving up and down again».

    ПЕРВОЕ. Главный тормоз — дополнение строк нулями, которое квадратичное по скорости.
    for i:=length(s1)+1 to m do
             s1:='0'+s1;
          for i:=length(s)+1 to m do
             s:='0'+s;


    Как решить?
    function add1(const large,small:string):string;
    
    function add(const x, y : string) : string;
    begin
      if length(x) > length(y)
        then add := add1(x, y)
        else add := add1(y, x);
    end;


    Ну и разумеется, сделать, чтобы add1 работала с числами разной длины.

    ВТОРОЕ. У вас, по-видимому, ошибка — 99+1 = 100 не создаст третьего разряда.

    ТРЕТЬЕ. Я не знаю, какой у вас Паскаль, но, вероятно, передача строк по const/var также повысила бы скорость.

    ОФТОП. Если ваша задача не «ввести два числа, сложить и всё», я бы отделил длинное число от его строкового представления, примерно так.
    TLongNum = record
      length : integer;
      data : array [1..1000] of byte;
    end;
    Ответ написан
    1 комментарий
  • Как собрать библиотеку .lib [muParser]?

    @Mercury13
    Программист на «си с крестами» и не только
    Ну, раз уж решил пойти третьим путём (Как подкючить библиотеку [muParser] к Qt? ) — лови проект.

    Как вы видите, в большинстве случаев проект библиотеки строится тривиально: ищем, что надо включить в DEFINES, и затыкаем предупреждения.
    CONFIG -= qt
    
    TEMPLATE = lib
    CONFIG += staticlib
    
    CONFIG += c++11
    
    # The following define makes your compiler emit warnings if you use
    # any Qt feature that has been marked deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS MUPARSER_STATIC
    
    QMAKE_CXXFLAGS += -Wno-deprecated-copy -Wno-cast-function-type
    
    # You can also make your code fail to compile if it uses deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    
    SOURCES += \
        src/muParser.cpp \
        src/muParserBase.cpp \
        src/muParserBytecode.cpp \
        src/muParserCallback.cpp \
        src/muParserError.cpp \
        src/muParserInt.cpp \
        src/muParserTest.cpp \
        src/muParserTokenReader.cpp
    
    HEADERS +=
    
    INCLUDEPATH += include


    (ВНИМАНИЕ! Я использую новейший MinGW из MSYS, он на две версии новее, и, возможно, некоторые из предупреждений, которые я заглушил, не нужны.)

    В программе придётся указать
    DEFINES += MUPARSER_STATIC
    
    INCLUDEPATH += ../MuParser/include
    
    LIBS += -L$$PWD -lmuparser


    Если что, в MSYS тоже есть MuParser, хотя он у меня не установлен.
    pacboy sync muparser:i muparser:x
    Ответ написан
    Комментировать