Python

Ускорьте работу программы (готовый правильный код написан уже)

Проходит 101 тест, на 102(при чем входные данные этого теста не указаны) превышает лимит по времени
лимит по времени 1 сек, а выполняется 102 тест за 1091ms
как можно ускорить код?
https://ideone.com/ezAdYv

У меня получился вот такой вот достаточно странный вариант: https://onlinegdb.com/KkV-um3IX с одним массивом.
Цикл перемещения одной машины меньшей группы (включая установку кармана перед очередной машиной меньшей группы) имеет длину 2 *max(n, m) + 2 действий.
Зная кол-во циклов, сразу можем расставить машины в нужном порядке - на конец ближайшего завершившегося цикла.
После чего находим положение и заполненность кармана.
АН
Алексей Николаич
89 160
Лучший ответ
Сергей Задорнов насколько все проще оказалось =)
Никита Самошкин прошло все тесты и по времени тоже, спасибо большое
Я бы тупо завел 3 списка
lstn, karman и lstm

Допустим, пропускать должен lstn
помещаем в karman крайний левый элемент из lstn, удаляя его из lstn и затем делаем к lstn append всех элементов lstm подряд. В результате lstm становится пустым, и элемент из karman оказывается в данном случае крайним правым. После "освобождения" karman путем переноса его элемента в lstm, ранее перемещенные элементы из lstm в lstn возвращаются обратно, становясь перед "переехавшим из karman", и karman оказывается снова перед новым крайним левым элементом lstn.

И так пока не закончится счетчик p или новый lstm не станет равен старому lstn, а karman пустым, то есть, все машины переехали...

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

Когда программа завершится - вывести текущее состояние списков

lstn karman (между двумя точками) lstm
Вячеслав Иванов Ускорить можно путем промежуточного подсчета длин операций, то есть, не выполнять последовательно кучу перемещений по одному элементу между длинными списками, на что уходит время, а прикидывать, что если в списке 10 элементов, а p=20, то можно сразу перебросить туда-сюда весь список, а не "крутить" его по одному элементику... Затем сразу уменьшить величину p на 10.
Писец) Это задача на два дня: За день наговнокодить, чтобы хотя бы работало, и за второй день анализировать и переписать нормально.

Это попытка заранее посчитать необходимую позицию и сразу собрать нужную строку.

print( fun(10000, 10000, 2000000000) ) # справляется за 0.2 - 0.3 сек
____________________________

n, m, p = map(int, input().split())

def range_str_r(start, end):
    s = ''
    for k in range(start, end):
        s += str(k) + ' '
    return s

def range_str_l(start, end):
    s = ''
    for k in range(start, end):
        s += ' ' + str(k)
    return s

def fun(n, m, p):
    if p == 0: # Ничего не меняет, сразу выдать начальную строку.
        return range_str_r(1, n + 1) + '..' + range_str_l(n + 1, n + m + 1)

    ###
    _min_ = min(n, m)
    _max_ = max(n, m)

    ###
    all_moves = _min_ * 2 * (_max_ + 1) - _max_

    if p >= all_moves:
        return range_str_r(n + 1, n + 1 + m) + '..' + range_str_l(1, n + 1)

    ###
    p -= 1

    moved = int( (p + _max_ + 1) / ((_max_ + 1) * 2) ) # сколько чисел уже перенесено
    is_empty = p // (_max_ + 1) % 2 == 1 # карман пустой?
    cut_at = int( p % ((_max_ + 1) * 2) % (_max_ + 1) )
    # в каком месте разрезаны переносимые числа

    if (is_empty):

        if (n <= m):
            return (
                range_str_r(1, n + 1 - moved) +
                range_str_r(n + 1, n + 1 + m - cut_at) +
                '..' +
                range_str_l(n + 1 + m - cut_at, n + 1 + m) +
                range_str_l(n + 1 - moved, n + 1)
            )

        else:
            cut_at = _max_ - cut_at

            return (
                range_str_r(n + 1, n + 1 + moved) +
                range_str_r(1, n + 1 - cut_at) +
                '..' +
                range_str_l(n + 1 - cut_at, n + 1) +
                range_str_l(n + 1 + moved, n + m + 1)
            )

    else:
        if (n <= m):
            cut_at = _max_ - cut_at

            return (
                range_str_r(1, n - moved) +
                range_str_r(n + 1, n + 1 + m - cut_at) +
                '.' + str(n - moved) + '.' +
                range_str_l(n + 1 + m - cut_at, n + 1 + m) +
                range_str_l(n + 1 - moved, n + 1)
            )
        else:
            return (
                range_str_r(n + 1, n + 1 + moved) +
                range_str_r(1, n + 1 - cut_at) +
                '.' + str(n + 1 + moved) + '.' +
                range_str_l(n + 1 - cut_at, n + 1) +
                range_str_l(n + 1 + moved + 1, n + 1 + m)
            )
Никита Самошкин спасибо, но тоже по времени долго выполнялось
это оказалось куда сложнее.
Жасын Сардаров ПОДОЖДИ Я ОШИБСЯ, НЕ ДОДЕЛАЛ
Руслан Лукьянов можете пожалуйста с пробелами как нибудь привести (на тот же ideone загрузить) а то непонятно так
Руслан Лукьянов не работает для 3 теста (на скрине есть)
Я тож немного на гуанокодил.

https://pastebin.com/mD7dy53a

def build_ans(N, M, Nleft, Nright, Mleft, Mright,dir=0):
~~ansNleft = [str(i) for i in range(1,Nleft+1)]
~~ansNright = [str(i) for i in range(N-Nright+1,N+1)]

~~pocket=['..']

~~if N-Nleft-Nright!=0:
~~~~pocket = ['.'+str(N-Nright)+'.']
~~if M-Mleft-Mright!=0:
~~~~pocket = ['.'+str(N+1+Mleft)+'.']

~~if dir==0:
~~~~ansMleft = [str(i) for i in range(N+1,N+Mleft+1)]
~~~~ansMright = [str(i) for i in range(N+Mleft+1,N+M+1)]
~~~~ans_list = ansNleft+ansMleft+pocket+ansMright+ansNright
~~else:
~~~~ansMleft = [str(i) for i in range(N+1,N+Mleft+1)]
~~~~ansMright = [str(i) for i in range(N+M-Mright+1,N+M+1)]
~~~~ans_list = ansMleft+ansNleft+pocket+ansNright+ansMright
~~return ' '.join(ans_list[:])

def count_roll(p, c_max):
~~per = 2*c_max+2
~~mod_per = p % (2*c_max+2)
~~if mod_per < 2:
~~~~return c_max
~~elif mod_per == per/2 or mod_per == (per/2+1):
~~~~return 0
~~elif mod_per > 1 and mod_per < per/2:
~~~~return (c_max - (p%int((2*c_max+2)/2) - 1))
~~elif mod_per > (per/2+1):
~~~~return (p%int((2*c_max+2)/2)-1)

def calc_nc(N,M,P):
~~if N<=M:
~~~~Nrp = (P+M) // (2*M+2)
~~~~Nlp = N - (P+2*M+1) // (2*M+2)
~~~~Mrp = count_roll(P, M)
~~~~Mlp = M - Mrp
~~~~d=0
~~else:
~~~~Mlp = (P+N) // (2*N+2)
~~~~Mrp = M - (P+2*N+1) // (2*N+2)
~~~~Nlp = count_roll(P,N)
~~~~Nrp = N - Nlp
~~~~d=1
~~return Nlp,Nrp,Mlp,Mrp,d

def get_position(N,M,P):
~~if N<=M:
~~~~P_max=2*N*(1+M)-M
~~else:
~~~~P_max=2*M*(1+N)-N

~~if P >= P_max:
~~~~return build_ans(N,M,0,N,M,0)
~~elif P == 0:
~~~~return build_ans(N,M,N,0,0,M)
~~else:
~~~~Nlp,Nrp,Mlp,Mrp,d = calc_nc(N, M, P)
~~return build_ans(N,M,Nlp,Nrp,Mlp,Mrp,d)

N, M, P = map(float, input('Введите кол-во машин слева (N), справа (M) и кол-во шагов (P) через пробел\n').split())

print(get_position(int(N),int(M),int(P)))

скорость выполнения не измерял, но логика также как и у элипсиса эклипса основана на вычеслении количества машин справа и слева от кармана.
Амир Азизов
Амир Азизов
1 363
Никита Самошкин спасибо, но тоже по времени долго выполнялось