Ответы пользователя по тегу Программирование
  • Как сделать взаимодействие между несколькими процессами?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Это называется IPC (inter-process communication). Гуглите IPC + ваш язык программирования, что-то да найдете. Полно библиотек готовых. Есть способы по-производительнее сокетов (всякие отображаемые в память файлы, например), но велосипед тут переизобретать смысла нет, если это только не задание на курсе по программированию.

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

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

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Мешать можно. Особо память это не сократит, а реализацию сильно усложнит.
    Ответ написан
    Комментировать
  • Как решить задачу "Шестерки" с меньшими затратами памяти?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Выведите 6^2, 66^2 и так далее. N до 20 хотя бы. Посмотрите на числа. Можете ли вы угадать цифру на заданной позиции без подсчета всего числа?

    Подсказка, вы получите вот такие вот числа:
    36
    4356
    443556
    44435556
    4444355556
    444443555556
    44444435555556
    4444444355555556
    444444443555555556
    44444444435555555556
    4444444444355555555556
    444444444443555555555556
    44444444444435555555555556
    4444444444444355555555555556
    444444444444443555555555555556
    44444444444444435555555555555556
    4444444444444444355555555555555556
    444444444444444443555555555555555556
    44444444444444444435555555555555555556
    4444444444444444444355555555555555555556


    Этот паттерн можно и доказать. Надо лишь представить возводимое в квадрат число как (10**n-1)2/3 и применить чуть-чуть элементарной алгебры, вроде формулы квадрата разности.
    Ответ написан
    Комментировать
  • Как правильно рассчитать коэффициент полезного использования пространства?

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

    Можно ускорить алгоритм сжатием координат: вввпишите все x и y координаты всех углов блоков, отсортируйте и унифицируйте (отдельно по каждой оси). Потом замените все координаты в блоках на порядковый номер в массиве уникальных координат. Примените алгоритм выше, но в конце надо помнить, что каждая ячейка теперь не 1x1, а сколько-то больше по вертикали и горизонтали.
    Ответ написан
  • Как сделать логику распространения файла?

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Обычно берут тип данных с запасом так, чтобы переполнения не было.
    Если же переполнение действительно может произойти, то есть несколько подходов:
    - игнорировать переполнение. Иногда это подходящий вариант. Например какая-нибудь CRC сумма для проверки целостности.

    - определять переполнение и как-то его бросать исключение или завершать программу. Все операции идут с проверками.

    - Clamped типы. Максимальное значение типа считается бесконечностью. Прибавление к нему не меняет это значение. Переполнение выдаст это максимальное. Все операции с переменной, естественно, тоже сопровождаются проверками. Тут есть возможность потом какие-то выводы о значении счетчика потом даже делать. Вы будете видеть, что там больше или равно INT_MAX, но насколько больше - знать не будете.

    - Wraparound. Часто вам не важно абсолютное значение счетчика. Нужно лишь знать, какое из двух значений больше. При этом вы знаете, что сравниваемые значения не могут быть слишком большими. Тогда очень маленькое значение будет считаться больше очень большого. Два примерно одинаковых будут сравниваться как обычные числа. Так можно делать, например, с sequence number пакетов. Если вы получите пакет с номером 0x02 после покета с номером OxFFF1, Можно с спокойно считать, что это номер после переполнения. Ну не будет сеть задерживать перетасовывать 65 тысяч пакетов.
    Ответ написан
    1 комментарий
  • Почему мой код не проходит по времени?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас не самое эффективное решение. Что-то типа O(n sqrt(n)), когда как задачу можно решить за O(n).

    Сначала решетом эратосфена найдите для каждого числа минимальный простой делитель. У меня даже статья про этот алгоритм есть с кодом и объяснением.

    Потом, решение за O(n log n) - можно быстро найти все простые множители каждого числа используя массив с предущего шага. Считайте степени простых множителей и перемножайте их +1. Так 2^2*3^1 имеет (2+1)(1+1) = 3*2 = 6 делителей (включая 1 и 12. Если они не нужны, вычтите 1-2 в конце).

    Но можно сделать еще быстрее. Фактически применив динамическое программирование. Во втором массиве посчитайте степень минимального простого делителя для каждого числа. Если мнимальный делитель (p[i]) для i равен мнимальному для i/p[i], то степень для i будет 1 + степень для i/p[i]. Иначе она будет 1. Так же посчитайте для каждого числа что там останется, если выкинуть все вхождения минимального делителя. Потом в другом массиве посчитайте для каждого числа количество делителей - это ответ для числа без всех вхождений минимального, умноженный на количество этих минимальных делителей +1. Ну а потом по этому массиву считайте сумму. Это будет работать за O(n).
    Ответ написан
  • Как находить лучший способ решение задачи на олимпиадном программировании?

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

    А так - на до сначала построить математическую модель задачи. Понять, на что эта модель похожа. Может, тут граф нарисовать можно? Какие алгоритмы на графы вы вообще знаете? Применимы ли они тут? Или это строка. Какие есть алгоритмы на строки? Смотрите еще ограничения. По ним обчно понятно, что тут нужно что-то за O(n), или за O(n log n) написать. Множество применымых алгоритмов еще больше уменьшается.

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

    Потом, очень частая тема - ДП. Попробуйте параметризировать задачу. Свести ее к подзадачам. Формализуйте ДП (считаем вот такую вот функцию от вот этих вот параметров вот с таким вот физическим смыслом).
    Ответ написан
    Комментировать
  • Какие темы самые важные для олимпиадного программировании в книге Кормена «Алгоритмы. Построение и анализ»?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Часть III. Структуры данных
    Часть VI. Алгоритмы для работы с графами

    Менее важные, но встречающиеся темы:
    Глава 30. Полиномы и быстрое преобразование Фурье
    Глава 31. Теоретико-числовые алгоритмы
    Глава 32. Поиск подстрок
    Глава 33. Вычислительная геометрия

    Но лучше прочитать, таки, всю книгу. Вправляет мозги, учит строить математические модели задач, что в олимпиадах очень важно.
    Ответ написан
    6 комментариев
  • Нужно ли делать защиту при делении на ноль?

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Если надо с чатиком, то нужна какая-то серверная часть. Серверную часть можно написать и на python, например, используя фреймворк django, но php или java какие-нибудь могут быть популярнее. Плюс какие-то базы данных там наверняка понадобятся, так что надо знать SQL. Клиентскую часть надо писать на разных языках в зависимости от платформы.
    Если это веб-приложение, то нужны javascript, typescript или scala. Плюс надо использовать один из сотни фреймворков, иначе задолбаетесь все с нуля писать. Ну и html c CSS надо знать, для оформления страницы.
    Если это приложение для смартфонов, то java или C++ + немножко java на андроиде, objective-c или swift на айфонах.
    Если это для винды приложение, то можно С++, java или python.
    Ответ написан
    Комментировать
  • Нужна концепция, часто ли используете блок схемы скриптов и чем пользуетесь?

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

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

    Все неравенства "==" замените на пару "<=" и ">=".
    Добавьте неравенства 1 < 2, 3 < 4 и т.д. для каждой пары соседних на числовой прямой чисел во входных данных

    Постройте граф: Каждой переменной и уникальному числу во входных данных сопоставьте одну вершину. Проведите для каждого неравнества ребро от меньшей вершины к большей, раскрашенное в 2 цвета: черный, если неравнество нестрогое (<=), белый - иначе.

    Теперь, если в этом графе нет циклов, содержащих белые ребра (строгие неравенства) - то противоречий нет: Все циклы целиком из черных ребер означают, что все вершины имеют одинаковое значение. Можно эти вершины все объединить в одну новую. Раз белые ребра (<) циклов не образуют, то получившийся граф будет ациклическим и можно назначить всем вершинам какие-то числовые значения, удовлетворяющие условиям. Проблема может еще быть, что нет целых решений вроде 1== a < b < c == 2, но это можно потом проверить в топологической сортировке жадно назначая всем вершинам числа. Или противоречия вида 2==3. Тоже решается после получения компонент связности.

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

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

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

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Суть проста: У вас есть два набора из N чисел. Две строки чисел одинаковой длины, если хотите. Надо в каждом столбце (из двух элементов) наверх поставить максимальный, а вниз - минимальный.

    Для решения этой задачи надо уметь в массивы, циклы, условные операторы и уметь поменять местами два значения. Код тривиален: пройдитесь циклом от 0 до N-1 (ведь нумерация с 0) и, если элементы в заданном столбце идут не в том порядке, в каком должны, поменяйте их местами.

    Код напишите сами. Хотя бы попробуйте.
    Ответ написан
    1 комментарий
  • Нейросети, пакеты, библиотеки, откуда такая сложность?

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

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

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

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

    Именно поэтому все эти универсальные библиотеки такие страшные.

    А decimal не работает, потому что у него не хватает точности. Плюс float работает быстрее ибо реализован аппаратно.
    Ответ написан
    4 комментария
  • Как сделать масштабирование правильно?

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

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

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

    Потом надо найти путь между заданными вершинами и вывести в ответ точки сочленения. Лучше ищите путь тем же DFSом, что и ищите точки сочленения. Так путь будет идти по дереву DFS. Надо найти в нем LCA двух искомых точек (Пик пути, после которого он пойдет вниз в другую ветку).

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

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

    То же и со вводом. Если надо как-то во внутренности очереди залезать и обычными push это не сделать, то, например, передавайте в метод CreateFromData() вектор введенных пользователем значений.
    Ответ написан
    Комментировать