• Почему выдает ошибку при наследовании?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Для решения этой проблемы по уму надо написать вот это в определении производного класса:
    using Array<T>::_size;
    using Array<T>::_capasity;
    using Array<T>::_data;


    Ответ на вопрос "почему" в С++ всегда один: "потому что стандарт":
    Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:


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

    Надо как-то компилятору указать, где искать вот эти ваши _size и т.д.
    Например, через this-> или через using или через Array<T>::.

    Вообще от этих правил lookup-а в C++ волосы дыбом встают и куча приколов вылезает. Их надо только запомнить. Оно неинтуитивно, но таково оно есть.
    Ответ написан
    Комментировать
  • Почему внутри шаблона можно иметь доступ к приватному члену внутреннего класса?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С чего вы взяли, что внутри шаблона это работет? Вы его инстанциировать пробовали (объявить переменную класса Outer<int>, например)?

    Вылезает точно такая же ошибка.

    Если шаблон просто написать, но не использовать его, то он компилироваться и не будет и ошибки в нем не обнаружатся.
    Ответ написан
    1 комментарий
  • Как решить ошибку Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Переведите текст ошибки на русский. У вас выход за границу массива. Запустите код в отладчике - он остановится в том месте, где это происходит.

    Возможно файл map.txt лежит не там, программа его не находит и не может его прочитать. Получается пустой массив file, но в функции GetMaxLengthOfLine идет обращение к 0-вому элементу, а его нет.

    Или строки в файле разной длины, тогда при присваивании map[x, y] = file[y][x]; идет выход за границу массива file[y] в не самой длинной строке. Ведь x проходится до длины самой длинной строки.
    Ответ написан
    1 комментарий
  • Как проверить эфективность линейного и бинарного поиска в простом методе сортировки?

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


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

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

    Но это плохая практика - стоит включать все, что вы используете всегда. Потому что потом вы что-то поменяете, исключив какой-то уже не нужный вам хедер отсюда, или из другого хедера, и у вас вылезет ошибка о неопределенных типах из cstdint.
    Ответ написан
    Комментировать
  • Какую роль играют float и double в скобках?

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

    float нужен вам в начале, потому что вещественные константы имеют тип double. Поэтому у eps/2.0 и 1.0 в первом цикле имеют тип double, все вычесляется в double. Преобразовав одно из выражений в float вы получаете то, что вам надо. Без этого все вычисления идут в double и ответ находится не тот. На самом деле там float при сравнении все-равно расширяется до double но на результат сравнения это не влияет в данном случае.

    Еще, вместо явного приведения типов, можно поставить f после вещественных констант, чтобы указать компилятору, что это float:
    while (1 + eps/2.0f != 1.0f){

    Тогда вычисления будут во float и ответ будет правильный.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас там бесконечный цикл, который читает ход Х. Без единого break внутри - поэтому нет даже теоретической возможности, что вы из него выйдите.

    Упростите код: эти 9 if else условий заменяются на такой код:
    if (us.length() != 2) {
      cout << "?????" << endl;
      continue;
    }
    int row = us[0]-'A';
    int col = us[1]-'0';
    if (row < 0 || row > 2 || col < 0 || col > 2) {
      cout << "????" << endl;
      continue;
    }
    if (pole[row][col] != '_') {
      cout  << "занято" << endl;
      continue;
    }
    pole[row][col] = 'X';
    break;
    Ответ написан
    Комментировать
  • Как эффективно составить гистограмму слов (big data)?

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

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

    Если памяти на компьютере не 64-128гб, и писать что-то не хочется, то можно файл отсортировать и потом подсчитать там повторения за один проход. Это будет чуть медленнее теоретически оптимального решения. rPman уже привел линуксовую команду, которая это делает. Только разбивать на части просто так нельзя, надо чтобы одинаковые строки остались вместе, иначе собирать ответ с нескольких кусков надо будет хитро. Но это и не надо в вашей задаче.

    Если же вы что-то распределенное все-таки хотите использовать, то ваша задача - это фактически обучающий пример для всяких map-reduce фреймворков типа hadoop. Но там придется повозиться с установкой и настройкой этого добра и код с примера скопировать.
    Ответ написан
    8 комментариев
  • Доказать рекуррентную формулу. Кто может решить? Что с этим вообще можно сделать?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    В задаче опечатка, там где-то должно быть J(n-2) вместо J(n-1), и в коэффициентах я не уверен.

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

    Осталось поэксперементировать перебирая разные части x^n и корня из квадртатного выражения: что из них интегрировать, а что дифференцировать.

    Интегрировать корень в знаменателе будет очень тяжко, там логарифмы какие-нибудь вылезут и вообще форма выражения будет совсем другой. Попробуйте продифференцировать 1/sqrt(), а оставшеюся часть интегрировать. Или можно домножить числитель и знаменатель на корень, тогда корень можно уже интегрировать, а оставшееся рациональное полиномиальное выражение дифференцировать.

    Еще можно с конца идти - перенесите все интегралы в одну сторону, сгрупируйте. Получите интеграл равен функции. Можно проверить равенство просто продифференцировав функцию.

    Похоже в задании опечатка - там должны быть J(n-1) и J(n-2), потому что дифференцируя вот эту свободную штуку получается (C1x^n+C2x^(n-1) + C3x^(n-2)) / sqrt(ax^2+bx+c). Значит, с другой стороны должны быть линейная комбинация J(n), J(n-1) и J(n-2).
    Ответ написан
    Комментировать
  • Как перемешать между собой слова создав новые?

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

    Стандартный алгоритм перемешивания таков:
    for i in range(len(a)):
      j = random.randint(0, i);
      a[i], a[j] = a[j], a[i]


    Тут поддерживается инвариант, что первые i элементов равномерно и случайно перемешаны. На каждой итерации выбирается случайная позиция для нового элемента (возможно последняя и элемент никуда не переместится). Дальше достаточно только лишь поменять новый элемент со стоящим на его месте. Ведь по инварианту все остальные элементы уже случайно перемешаны и в итоге случайно перемешанными оказываются N+1 элементов.
    Ответ написан
  • Как написать свое регулярное выражение?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Без теории тут никак.
    Тут 2 варианта: или стройте конечный недетерменированный автомат (с эпсилон переходами), который соответствует этому регулярному выражению и дальше применяйте стандартный алгоритм проверки. что автомат принимает заданную строку. Или второй вариант: пишите динамическое программирование "соответствует ли вот этот префикс заданной строки вот этому префиксу регулярного выражения".

    Конечный автомат будет и побыстрее работать и памяти меньше требовать.

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

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

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

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

    Тут подойдет что-нибудь вроде std::set в C++ - структура хранящая упорядоченное множество объектов, с доступом и изменением за логарифм, умеющая искать ближайший к заданному значению слева и справа (lower_bound, upper_bound). Хранить в ней мы будем вертикальные отрезки, помеченные номерами их прямоугольникв. Не знаю ее аналоги в других языках - нужно что-то реализованное или на binary search tree, или на skip list.

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

    В этой задаче можно забить на правые границы прямоугольников и на их ширину (раз нет пересечений). Соседями каждого отрезка - левого края будут ближайшие к нему левые края каких-то прямоугольников.
    Поэтому вам надо получить все отрезки заданные в виде {x, y1, y2, id} и отсортировать их (сначала по x, потом по y). Потом в этом порядке их обходите и применяйте новый отрезок к структуре данных. Все удаляемые отрезки + 2 пересекающихся сверху и снизу пойдут в список соседних для нового отрезка.

    Этот алгоритм за O(n log n) получит всех соседей для всех прямоугольников.
    Это что-то похожее вот на эту задачку с leetcode
    Ответ написан
    2 комментария
  • Может ли прерывание прервать выполнение конструктора / деструктора в С++?

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Можно при просчете вершины дерева игры выбирать не максимальное/минимальное значение из всех детей, а второе с конца с некоторой вероятностью. Значение вероятности задаётся уровнем сложности.
    Ответ написан
    Комментировать
  • Как запретить std:: vector перемещаться?

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

    Еще можно изменить ваш дизайн. Например, вместо vector использовать list, итераторы в котором не портятся от добавления. Или хранить вместо итераторов/указателей на элементы в векторе индексы.
    Ответ написан
    Комментировать
  • Можно в c++ ли работать с памятью через stream?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Класс std::stringstream как раз это и реализует.
    #include <stringstream>
    
    std::stringstream sout;
    sout << "some string " << 42;
    cout << sout.str();


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

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

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

    1) Проверить, что данный элемент надо удалить
    1.1) Проверить, что элемент не уникальный
    1.2) Проверить, что элемент - не первый среди одинаковых (один-то его надо оставить)
    2) Удалить элемент из массива дописав 0 в конце.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Сначала получите цифровую запись числа (подсказка: деление на 10 с остатком даст вам последнюю цифру и число без этой цифры).

    Далее, поскольку в задаче идет разговор о количестве цифр, вам надо подсчитать, сколько раз каждая цифра встречается. Получите массив из 10 счетчиков.

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

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

    Четвертая координата позволяет записывать одной матрицей повороты/растяжения и сдвиги. Если у вас матрица 3x3 (не "трехмерная" - у нее все так же есть только ширина и высота), то точка (0, 0, 0) всегда останется (0, 0, 0). Ведь на что 0 не домножай - останется 0. Поэтому матрицами 3x3 можно записать только повороты и сжатия, но не сдвиги.

    Поэтому вводят фиктивное четвертое измерение w. При этом удобно считать, что координаты точки (x, y, z, w) - Это (x/w, y/w, z/w). Это еще иногда называют однородными координатами. Еще один плюс этого объекта в том, что им можно описать точки на бесконечности (когда w = 0).

    Вот тут уже можно составить линейное преобразование (т.е. взять матрицу), которое оставляет w нетронутым, но использует его для сдвига:
    x' = a11*x + a12*y + a13*z + a14*w
    ...
    w' = w

    Вот в a14 - как раз и находится сдвиг по оси X.
    Ответ написан
    3 комментария