Задать вопрос
Ответы пользователя по тегу Python
  • Проблема с оптимизацией сортировки методом Bubble sort. Как ускорить сортировку для списка из 100 тысяч элементов?

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

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

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

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

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

    Увеличте размер сортруемых массивов до 100 000 или до миллиона и квиксорт должен стать быстрее.

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

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

    Надо генерировать ее сразу по номеру.

    Посмотрите на первый элемент. У первых (n-1)! перестановок там 1, у следующих (n-1)! - там 2, потом идет группа, начинающихся с 3 и т.д.

    Уже вы можете понять в какой группе искомая k-ая перестановка. Тупо floor(k/(n-1)!) (если нумерация с 0 и перестановок и групп). Фактически, формула для первого элемента - a[0] = (k-1)/(n-1)! + 1.

    Дальше вы можете выкинуть из рассмотрения первый элемент. Сфокусируйтесь на группе с заданным известным первым элементом. Какой номер искомая перестановка имеет среди этих (n-1)!? Надо из k вычесть количество перестановок c меньшими первыми элементами (их (a[0]-1)*(n-1)!. Потом задача сводится к преведущей - сгенерировать k-ую перестановку среди оставшихся n-1 элементов.

    Если использовать какое-нибудь дерево отрезков, чтобы быстро искать j-ый пока не занятый элемент, то все решение будет за O(n log n). Если делать совсем просто - двумя циклами - то будет O(n^2). Гораздо быстрее вашего O(n!).

    Надо только аккуратно обработать случаи, когда (n-1)! слишком большое. Фактически, вам надо найти максимальный факториал, который меньше k. Пока не спуститесь до этого момента нужно сразу брать первый незанятый элемент и не считать факториал вообще.
    Ответ написан
    Комментировать
  • Как создать матрицу расстояний для нескольких точек?

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

    Работать это будет O(nm) - быстрее никак.
    Ответ написан
    Комментировать
  • Как соединить в пары элементы двумерного массива?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Надо обязательно массив массивов? Или подойдут кортежи? Так-то есть zip.

    А дальше можно через np.asarray и map преобразовать массив touples в массив массивов.
    Ответ написан
  • Не работает код, ошибок нет. Что делать?

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

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

    Т.е. вам надо найти путь из одной клетки в другую, пройдя по как можно меньшему количеству клеток. Можно ходить в 8 направлений - если пересечь угол, то можно за одну точку на ломаной перейти по диагонали.

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

    Надо только аккуратно разобрать случаи, если начальная или конечная точка лежит на границе клетки.
    Ответ написан
    1 комментарий
  • ValueError: invalid literal for int() with base 10: '', что делать?

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

    Везде, где вы читаете из файла делайте:
    l = f.readline()
    print("The line is: \""+l+"\"")
    n = int(l)


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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Можно в несколько раз с оптимизировать, переписав на C++ c векторизацией (SSE там всякие). Тогда сравнение двух строк будет 1-2 инструкции вместо 15. Еще можно распаралеллить вычисления. Но все эти оптимизации все равное не позволят вам быстро считать для 100000 строк. Что уж говорить, сама матрица будет занимать минимум 10 гигабайт, если аккуратно на C писать или типизированный numpy массивы использовать. А так она и все 20 и 40 гигабайт займет запросто.

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

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

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

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

    Чтобы работало быстро вам надо не менять lst, а помнить индексы границ текущего куска.

    Ещё, вам надо останавливаться, когда рассматриваемый кусок станет пустым, чтобы решение не вылетало, если искомого числа в списке нет.

    И последнее, в питоне есть операция целочисленного деления - //. Используйте ее вместо приведения к int после деления.
    Ответ написан
    2 комментария
  • Как обрезать путь чтобы осталось только имя файла?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    for file in filename: переберет в file все символы строки filename.

    Вам надо просто передавать ваш filename в open.
    Ответ написан
    Комментировать
  • Python/numpy: как увеличить массив на одну строку без использования дополнительной памяти?

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

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

    Это даже в C++ сделать нельзя, не говоря уже о питоне.

    Edit: Вообще говоря в C++ есть realloc, Но оно не гарантирует расширение существующей области памяти. Ибо она может быть занята чем-то еще.
    Ответ написан
    1 комментарий
  • Как посчитать БЖУ?

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

    Еще можно свести задачу к целочисленному линейному программированию. Вводите переменные - сколько штук каждого пункта съели, составляете линейные уравнения. Потом можно это все скормить какому-нибудь решателю. Сейчас много библиотек и они довольно быстро такие задачи щелкают. Гуглите "integer linear programming solver".
    Ответ написан
  • Алгоритм поиска минимального количества ходов, требуемых для приведения всех элементов к одному числу (Python)?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Во-первых, в вашем алгоритме цикл while вообще не нужен. Сколько нужно операций +1, чтобы из a получить a+12345? Ровно 12345. Вам надо просто вычесть одно число из другого.

    Далее, мысль должна быть такая: Вот вы знаете, сколько нужно операций, чтобы все числа в массиве привести к X. Вопрос: сколько операций вам понадобится для приведения всех чисел к X+1? (Подсказка - если число было меньше X, то теперь понадобится на 1 операцию больше. Если число было больше X - то понадобится на 1 операцию меньше).

    Теперь вам надо посмотреть, подумать и выбрать оптимальное X, которому вы будете приводить все числа. Ваш вариант с max/2 не оптимален.
    Ответ написан
    5 комментариев
  • Как решить задачу, используя одну формулу и не успользуя if, else, elif?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Бинарный поиск.
    Можно реализовать без if-ов вообще.
    Суть в том, что у вас есть текущий отрезок. Находите середину, спрашиваете про нее. Получаете ответ R = 0 или 1. Потом прибавляете половину отрезка к левой границе, умноженную на R и вычитаете ее из правой границы, умноженную на 1-R. Таким образом сдвинется только одна граница. Остается вопрос, что делать с выходом из цикла. Там же внутри if запрятан.

    Можно или скопировать код 7 раз (2^7 > 100), или иметь бесконечный цикл, который будет сравнивать границы и вызвать одну из двух функций в массиве на 2 элемента. Одна из функций выведет ответ и завершит работу программы через exit. Вторая - не будет делать ничего.
    Ответ написан
    Комментировать
  • Как решить данную задачу на python?

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

    F(i,k) - максимальная сумма, которую можно получить из первых i троек, такая что ее остаток от деления на 4 равен k.

    База: F(0,0) = 0, F(0,k) = -infinity.
    Ответ: F(n, 0).

    Пересчет
    F(i,k) = max(F(i-1, ((k-a[i][0]-a[i][1])%4+4)%4)+a[i][0]+a[i][1], 
                 F(i-1, ((k-a[i][1]-a[i][2])%4+4)%4)+a[i][1]+a[i][2], 
                 F(i-1, ((k-a[i][0]-a[i][2])%4+4)%4)+a[i][0]+a[i][2])


    Только лучше вместо -infinity как-то отмечать, что позиция (i,k) недопустима (нельзя первыми i тройками набрать сумму с остатком k. И недопустимые варианты при выборе максимума выбирать ненадо.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Список/массив на n элементов.
    Ответ написан
    Комментировать