Python-оптимизация алгоритма динамического программирования из codechef
StasFomin (обсуждение | вклад) |
StasFomin (обсуждение | вклад) |
||
Строка 65: | Строка 65: | ||
А потом парсить и отдавать результаты генератором. | А потом парсить и отдавать результаты генератором. | ||
+ | Делаем {{diff|1=digprime.py|20478|такие правки}} и получаем | ||
− | {{oldid|1=digprime.py|2=20468| | + | {{oldid|1=digprime.py|2=20468|версию, которая работает абсолютно также}} по результату, возможно чуть медленней перекопированием ввода в память (если померять у себя), но возможно быстрее, чем у них на сервере, с задушенным IO. |
− | + | ||
+ | В любом случае, сначала надо избавиться от NZEC, потом уже заниматься оптимизацией. | ||
+ | |||
+ | [https://www.codechef.com/viewsolution/63961222 Ага, от NZEC уже избавились], | ||
+ | но теперь здравствуй TL. | ||
+ | |||
+ | [[File:Python-оптимизация алгоритма динамического программирования из codechef_2022-05-01_03-36-58_image0.png||400px]] | ||
+ | |||
+ | Может если [https://www.codechef.com/viewsolution/63961211 перейти на PYPY], скомпилируется и пройдет? | ||
+ | |||
+ | Увы, нет. | ||
+ | |||
+ | [[File:Python-оптимизация алгоритма динамического программирования из codechef_2022-05-01_03-34-48_image0.png||400px]] | ||
+ | |||
+ | Обращаю внимание — 10.01 и 4 секунды это не время работы программы! Это сколько |
Версия 00:38, 1 мая 2022
При разборе ваших решений, столкнулся с одной из попыток, с результатом «вроде все сделано правильно, но система не пропускает, наверно что-то не так с системой или вообще питон не потянет, вот на плюсах все решают и все хорошо».
Попробую кратко показать, как можно системно поработать с улучшением решения, даже не особо вьезжая в алгоритм (ну при условии, что идея будет правильна).
Видим вроде типичный алгоритм ДП, смотрим описание задачи Codechef/DIGPRIME, переходим по ссылке Editorial на разбор и разъяснение задачи, но даже если этой ссылки не будет, смотрим список принятых решений:
Берем из них любое принятое CPP-решение, сохраняем его в файл digprime-good.cpp компилируем его
gcc -g -o digprime-good digprime-good.cpp -lstdc++
Итак, у нас есть референсное решение.
Смотрим на описание задачи, особенно на секцию «ограничения»…
и пишем примитивных генератор «digprime-generate.py», такой, чтобы задействовать все ограничения (вдруг все проходит на минимальных данных, но где-то что-то переполняется на самых крайних случаях), плюс большой тестсет даст возможность разумно измерять время работы.
import numpy as np num = 100000 print(num) for t in range(num): print(np.random.randint(1,1000000000000000000))
Генерим наш тестовый набор:
python digprime-generate.py > big-samples.txt
Генерим результаты нашего алгоритма и референсной реализации на тех же входных данных:
digprime-good < big-samples.txt > reference-good.txt python digprime.py < big-samples.txt > big-our-results.txt
Сравниваем («meld», «winmerge», «fc», ) — используйте то, что ставится на вашу ось и есть под рукой, но в данном случае, совпадение добайтовое даже по ответу «md5sum»:
md5sum big-our-results.txt e602cd2d36e9c6749764cace13774bdc big-our-results.txt
md5sum reference-good.txt e602cd2d36e9c6749764cace13774bdc reference-good.txt
Вроде же все в абсолютном порядке, но что выдает codechef?
Ошибка «NZEC» — «какая-то ошибка», увы, без малейших подсказок на чем, и что за ошибка. Но по времени работы — доли секунды, предположим, что что-то сразу с вводом.
Тут на самом деле наблюдались разные проблемы в этих (codechef, spoj) тестовых системах. То что-то не так с буферизацией, и какой-то перевод строки становился пробелом, или длинная строка, и input() не вычитывал ее до конца, то большое количество операций input, а там перенаправление на чтение из файла, много IO операций, срабатывают какие-то контейнерные ограничения или просто будет тормозить.
Поэтому, лучше сразу сделать чтение типа
lines = sys.stdin.readlines() content = " ".join(lines).strip()
А потом парсить и отдавать результаты генератором.
Делаем такие правки и получаем
Old revision of <tvar name=1>версию, которая работает абсолютно также</tvar> по результату, возможно чуть медленней перекопированием ввода в память (если померять у себя), но возможно быстрее, чем у них на сервере, с задушенным IO.
В любом случае, сначала надо избавиться от NZEC, потом уже заниматься оптимизацией.
Ага, от NZEC уже избавились, но теперь здравствуй TL.
Может если перейти на PYPY, скомпилируется и пройдет?
Увы, нет.
Обращаю внимание — 10.01 и 4 секунды это не время работы программы! Это сколько