Ответы пользователя по тегу Python
  • Как исправить ошибку IndentationError: unindent does not match any outer indentation level?

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

    В питоне нет фигурных скобок, как в си, или begin/end, как в паскале. Содержимое блока (if/for) выделяется отступом.
    Ответ написан
    Комментировать
  • В чем здесь ошибка?

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

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

    Вам надо или строку развернуть, или номера разрядов пересчитать, учитывая длину строки.
    Ответ написан
    Комментировать
  • Как делать спиральные массивы?

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

    Выписываете прямые куски - какой они длины, в какую сторону вращаются. Ищите паттерн (например в спиральном массиве из центра длины кусков: 1, 1, 2, 2, 3, 3, ...).

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

    Для реализации поворота храните текущее направление в виде двух переменных dx, dy. Одна из них +-1, а другая 0. Для поворота против часовой стрелки делаете (dx, dy) = (-dy, dx)
    Ответ написан
    Комментировать
  • Как можно найти все пути между вершинами графа networkx?

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

    Готового решения нет, потому что это довольно редкая задача - получить все пути. Кстати, даже без самопересечений путей может быть экспоненциально много. Уже для для 15 вершин есть тривиальный граф, в котором почти 100 миллиардов простых путей между любыми двумя вeршинами.

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

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

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

    def dfs(v, end, graph, path, visited):
      if v == end:
        print(path)
        return
      for u in graph.neighbours(v):
        if u not in visited:
          path.append(u);
          visited.add(u);
          dfs(u, end, graph, path, visited)
          path.pop();
          visited.remove(u);
    
    // вызывать dfs(start, end, graph, [], set())
    Ответ написан
    Комментировать
  • Как преобразовать массив в новый со следующими значениями?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    print ([("small" if a < 20 else "medium") if a <=30 else "large" for a in a_random])
    Ответ написан
  • Как построить симуляцию луча?

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

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

    Отражения, если вам так хочется, можно делать через вектора. Есть у вас вектор вдоль луча, и вектор вдоль зеркала и нормаль внутрь. Через скалярное произведение можно разложить вектор луча на перпендикуляр и паралледьный к зеркалу. Потом надо развернуть вектор перпендикуляр и сложить их.

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    У вас решение за O(N^2), когда как можно сделать решение за O(N). Тут не в питоне дело, а в плохом алгоритме.

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

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

    Я не совсем питонист, но вот примерный код:

    def days_till_warming(T):
        counts = []
        stack = []
        for i, curr_temp in enumerate(reversed(T)):
            while len(stack)>0 and stack[-1][0] <= curr_temp:
                stack.pop()
            delta = i - stack[-1][1] if len(stack) > 0 else 0
            stack.append([curr_temp, i])
            counts.append(delta)
        return list(reversed(counts))
    Ответ написан
    Комментировать
  • Как создать радиус в любое расстояние м/км расположенного вокруг координаты и получить список этих координат?

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

    Вам придется или скопировать код по ссылке и переписать на питоне, или использовать этот пакет.

    Дальше, вам надо начиться отступать от заданной точки на север или восток на 1 метр. Это можно или медетировать над формулой выше а можно просто запустить бинарный поиск, который будет искать изменение широты или долготы. Пусть d - сколько вам надо отложить в метрах, R - радиус земли в метрах. Тогда ищите изменение на отрезке (0, 4*r*180/(2*Pi*R)). Пробуйте откладывать текущее значение по широте или долготе, считайте расстояние по формуле и, если оно больше d, заменяйте верхнюю границу отрезка на середину, иначе заменяйте нижнюю границу. Остановите бин.поиск, когда отрезок станет достаточно мелким (например <1e-10).

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

    Сначала сгенерируйте точки на одной вертикале с начальной. Для этого повторно откладывайте 1м на север и юг от нее, пока расстояние до (x0,y0) не превысит ваш радиус. Бинпоиск достаточно запустить ровно один раз в самом начале и дальше именно это приращение откладывайте вверх и вниз.

    Потом аналогичным образом откладывайте от каждой сгенеренной точки новые точки на запад и восток. Сначала для каждой точки бинпоиском найдите нужное приращение по долготе. Потом откладывайте его влево и вправо, пока не выйдите за радиус от (x0,y0).
    Ответ написан
  • Как рассчитать "похожесть" двух словарей?

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

    В вашем примере это будет (1-2)^2+(2-2)^2+(3-0)^2+(1-0)^2 = 11.
    Чем меньше это число, тем похожее словари. Можно ее еще как-то нормировать, поделив на, допустим количество уникальных ключей в обоих словарях. Или на количество всевозможных слов.

    Если ваш язык/структура позволяет пройтись по словарю в лексикографическом порядке, то можно подсчитать такую меру за линейное время выполняя что-то вроде слияния сортированных списков. Изначально 2 указателя на минимальные элементы (по словарю) в каждом словаре. Если два элемента с одинаковым ключем, то считайте разность двух весов и двигайте оба указателья. Иначе считайте разность веса с минимальным ключем и 0 и двигайте только этот указатель. Случай, когда один из словарей уже пуст совпадает со вторым случаем.

    В питоне позволяет обходить ключи по порядку OrderedDict.
    Ответ написан
    Комментировать
  • Очень странно работает форматирование массива. В чем ошибка?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Внутри for item in array нельзя удалять или добавлять элементы. Итерация слетает.

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

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Определитесь со смыслом start и finish. start - это первый элемент интервала, в котором искомый x может быть. finish, судя по тому, что он равен сначала len(lst) - это за концом интервала (не входит в него).

    Значит, исходя из этого, надо цикл гнать пока start < finish - тут правильно.

    При переходе наверх надо start делать mid+1 - тут правильно.

    При переходе вниз надо finish делать mid - тут ошибка! Ведь только что рассмотренный элемент вы выбрасываете, раз он не подошел. Но предыдущий за ним может быть искомым. Нельзя делать finish = mid-1 - вы теряете потенциально важный элемент.

    Другой вариант исправления - изменить смысл finish быть концом отрезка включительно. Тогда присвоения в цикле правильные, но неверно условие цикла и инициализация. Нужно гнать цекл пока start <= finish и изначально присваивать len(lst)-1.
    Ответ написан
  • Python массивы не пашет нужна помощь, что делать?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    У вас массив интов создается:
    massive = array('i', [])

    А пихаете вы туда символ:
    massive.append(random.choice(string.ascii_letters))


    О чем вам интерпретатор и говорит:
    TypeError: an integer is required (got type str)
    Ответ написан
  • Как работают классы в Python?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    https://docs.python.org/3/tutorial/classes.html#cl... - инструкции внутри class выполняются один раз.
    Обычно там пишут определения методов и членов класса. Точно так же, как у вас в коде ниже написано определение функции test_def. Определение всегда выполняется.
    Ответ написан
    Комментировать
  • Как составить массив из чётных элементов матрицы на Python?

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

    edit:
    А еще у вас при обходе матрицы только один цикл. А надо так же как при вводе делать двумя вложенными циклами.
    Ответ написан
    Комментировать
  • Как максимально оптимизировать код Python?

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

    Есть вот такая формула. Для каждого простого числа можно опредерить степень просто деля n (не факториал!) на это простое число нацело, пока не получится 0 и суммировать все результаты.

    Но это работет только для простых чисел. Т.е. чтобы узнать, в какой степени число 10 входит в N! (или сколько нулей на конце в деситичной записи) надо узнать, сколько раз 2 и 5 входят в N! и взять минимум.

    Т.е. надо разложить k на простые множители, для каждого простого множителя подсчитать, сколько раз он входит в n! по формле выше. Потом поделить это на степень простого числа в k, и по всем делителям k взять минимум.
    Ответ написан
    Комментировать
  • Какой алгоритм для поиска подстрок в списке кортежей будет быстрее comprehension?

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

    Все ваши ключи складываете в бор, как описано по ссылке. Потом для каждого кортежа выполняйте поиск в строке i[1], если нашли, то добавляйте ваш id в ответ.
    Ответ написан
    3 комментария
  • Как построить функцию декодирования классического кода Элиаса, если прямое кодирование работает правильно?

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

    И читайте это:
    1) подсчитайте сколько нулей идет в начале строки.
    2) Это сколько бит надо прочитать дальше и перевести в десятичную систему счисления.
    3) Это столько бит, сколько нужно прочитать дальше и перевести в десятичную систему, чтобы раскодировать число.
    Ответ написан
    Комментировать
  • Python. Найти расстояние от точки до прямой, зная координаты этой точки?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Составьте уравнение прямой вида a*x+b*y+c=0.
    Подставьте в это уравнение координаты точки. Возьмите по модулю и поделите на sqrt(a^2+b^2).
    Ответ написан
    Комментировать
  • Как решить задачу по рекурсивным алгоритмом на python?

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

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

    Вместо этого используйте цикл while:

    while add:
      item = add[0]
      add.remove(item)
      s.append(item)
    ...


    Вторая большая ошибка, в питоне списки передаются по ссылке! Поэтому s, который у вас параметр рекурсивной функции, на каждом уровне один и тот же список. Но при выводе множества вы сразу же возвращаетесь из функции, не удаляя item из s. Вам надо чтобы все изменения в s были отменены по выходу их функции. Перед return делайте s.remove(item).

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

    Еще по коду:
    range(n) в python возвращает 0..5. У вас там цикл по ребрам в __main__ и там идет обращение к i-1 в массиве graf. Т.е. обращение к [-1]. Вряд ли вы это хотели. Работает по чистой случайности, потому что в питоне a[-1] дает последний элемент.

    И вообще, вы матрицу смежности строите, но нигде не используете.

    Вместо функции check(), вы сделайте нормальный список смежности один раз, а то просто глаз режет от неоптимальности.
    neighbors = [[] for i in range(count_vershin)]
    for edge in graf:
      neighbors[edge[0]-1].append(edge[1]-1)
      neighbors[edge[1]-1].append(edge[0]-1)
    Ответ написан