Задать вопрос
  • Как написать на СИ программу, которая выделяет числа из строк?

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

    Сама программа идет по строке, если видит, что текущий символ - цифра, то запускает функцию выше. Потом выводит от текущего до найденного символа, потом сдвигает текущий индекс на конец числа. Лучше делать while. Внутри вы или увеличиваете индекс на 1, если текущий символ - не цифра, или сдвигаете его на конец найденного числа.
    Ответ написан
    Комментировать
  • Segmentation fault (core dumped) как пофиксить?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Пройдитесь по коду отладчиком. Ну, или добавьте отладочный вывод: например, в начале цикла while и цикла for выводите, что происходит итерация цикла и переменные c,i такие-то.

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

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

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

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

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

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

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

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

    Чтобы не возиться с удалением соседей, помещайте вершины удаленными и при обходе списка соседей удаляйте их
    Ответ написан
  • Как минимизировать логическое уравнение?

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

    А дальше там будет 2 соседних слагаемых A !B !C !D+A C !D. Тут можно A !D вынести за скобки и останется (!B !C+C). Это можно сократить просто до !B + C. Было такое правило, вроде бы, но это можно доказать. Если C истинно, то исходное уже истинно. Если !B истинно, то либо !С истинно и истинно первое слагаемое, либо С истинно, и истинно второе слагаемое.

    Вот уже третье слагаемое сократилось то A !B !D

    Потом повторите фокус, вынеся за скобки из первого и второго слагаемого !B. Там останется !A+A !D = !A + !D
    Ответ написан
    3 комментария
  • Для чего нужен возврат значения по ссылке?

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

    Вот тут вы взяли ссылку, которую вернула func и скопировали значение в переменную b. Поэтому ниже &b выведет вам адрес переменной b, а не то, что вы хотели.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Воткните эту фразу в гугл транслейт. Там все понятно написано. Нельзя объявлять переменную прямо в цикле (int i) в том режиме, в котором у вас работает компилятор. Надо что-то в свойствах IDE поковырять и включить режим C99.

    Ну, или объявляйте переменную i до цикла.
    Ответ написан
    2 комментария
  • Как реализовать дерево на основе связного списка?

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

    Возможно, вам надо хранить детей каждой вершины в виде связного списка (тогда у вас будет куча списков). Еще, популярный подход (фактически делающий то же самое) - это хранить в каждой вершине ссылку/указатель на первого ребенка и на следующего брата. Так все списки будут перемешаны в одну большую структуру. Но тут, правда, в отличии от связного списка, все равно есть 2 типа ссылок.
    Ответ написан
    2 комментария
  • Как скомпилировать c++ код через терминал на MacOS?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    И в чем проблема? Ставите command line developers tools, открываете терминал, запускаете g++, передаете параметром ваш исходник и ключи всякие.
    Ответ написан
    4 комментария
  • Если бы в компьютере было 3 уровня напряжения, то формула информации имела место быть?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Тут все завязано на то, что бит - это 2 состояния. Поэтому и логарифм двоичный. Если бы бит имел 3 состояния, то он не был бы 2 двоичных бита - нельзя так округлять (давайте вы свою квартплату так же до 100000 округлите, вам нормально?). Логарифмы были бы по основанию 3, ведь каждый новый трибит умножал бы количество возможных состояний на 3.
    Ответ написан
    6 комментариев
  • Самый эффективный способ поиска последовательности нулевых байт?

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

    Надо считать длину последовательности из нулей в начале и в конце блока и помнить длину последовательности заканчивающейся в конце предыдущего блока и продолжать ее в текущий блок.

    Если вы ищите короткую последовательность, то еще нужно прверить, что в текущем болке она встречается. Например, чтобы проверить, что в битовой маске М есть последовательность из 5 бит, можно проверить, что (M & M >> 1) && ((M & M >> 1) >> 2) & M >> 4 имеет ненулевые биты. Достаточно log k сдвигов и битовых И для поиска последовательности из K ненулевых бит.

    Но вряд ли вы будете с этим возиться. Следующий вариант - эмулировать SIMD руками в int64. Читайте из памяти по 8 байт (через memcpy в int64) и там уже проверяйте через LSB/MSB сколько нулевых байт на конце, в начале. Чуть сложнее, если вам надо искать последовательность короче восьми байт. Тогда надо еще отдельно проверить через битовые сдвиги, есть ли она внутри блока из 8 байт.

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

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

    Так можно по номеру получить уникальное подмножество и любое подмножество имеет какой-то номер. Все. Вот мы и занумеровали множество всех подмножеств натуральными числами. Оно счетно.
    Ответ написан
    2 комментария
  • Как работают переменные в низкоуровневом понятии?

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

    Самое простое - компилятор запоминает, что вот myvar - это переменная, которая лежит вот там-то в памяти. Грубо говоря, эти все имена переменных - это псевдонимы для адресов памяти. Если он видит в коде myvar = a + 1;, то он генерирует инструкцию, которая читает из фиксированного адреса переменной a, прибавляет 1 и сохраняет результат в адрес для переменной myvar.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Правильный ответ - ни так и не эдак. Никак. Сравнивать указатели не из одного и того же массива - undefined behavior. Это было недавно в статье на хабре. Там ссылаются на раздел 3.3.8, "Relational operators".

    Более того, у вас там в программе еще UB: нельзя обращаться к данным в переменной long через указатель short - Это нарушение strict aliasing.

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

    На практике - никаких лево и право там не существует, есть только младшие и старшие адреса, читайте про big/little endian порядки байт. Они там бывают и так и эдак в разных архитектурах. В x86, например, младший байт имеет меньший адрес.
    Ответ написан
    Комментировать
  • Как узнать расстояние между вершинами в дереве?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно получить список всех потоков одного процесса через Thread32First/Thread32Next (пример).

    Ищется в гугле буквально по "winapi list threads".
    Ответ написан
    Комментировать
  • Почему не читаются данные при вводе из файла?

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

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

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

    Там можно искать нужный вам элемент через floor или ceiling. Поиск и удаление, если создатели библиотеки в java хоть что-то слышали про алгоритмы и структуры данных, работают за логарифм.
    Ответ написан
    Комментировать