Написала код для задачи http://codeforces.net/problemset/problem/680/E (про медведя на клетчатом поле) на Python. Застряла на 12м тесте с вердиктом "Превышено ограничение времени на тесте 12". Попробовала максимально оптимизировать написаный код, но все равно не выходило пройти ограничение по времени. Запускала с помощью pypy2 (если запускать python2, то выходит в 6 раз медленнее).
Последняя попытка здесь: http://codeforces.net/contest/680/submission/18710430
Будучи уверенной, что в асимптотике все верно, попробовала переписать на плюсах, повторяя логику кода на питоне один в один.
Сдала с первой попытки: http://codeforces.net/contest/679/submission/18726182
- 12й тест, который не проходил на pypy2 с ограничением времени в три секунды, прошел за 561ms.
- 11й тест(предыдущий) прошел в с++ версии за время вдесятеро меньшее, чем на pypy2
Вопросы:
- Можно ли оптимизировать мой питоновский код, чтоб он таки прошел ограничение? При том, что 12й тест не самый тяжелый. В списке сдавших эту задачу нет ни одного питониста
- Почему ограничения на задачу выставлены таким образом, что абсолютно одинаковые решения на двух языках находятся в неравных условиях?
Я пишу впервые, так что не знаю публикуется ли где-то пост в открытом месте. Если никто не прочитает, то вопросы оставляю здесь как риторические
Я, конечно, не эксперт по питону, но попробую ответить.
Пожалуй, единственный выход — не писать на питоне сложные задачи.
Так выходит, что у меня еще ни одна задача на графах на питоне с первого раза не проходила по времени. Но раньше получалось в итоге оптимизировать код так, чтоб ограничения проходились: уменьшение числа используемых структур, отказ от туплов, отказ от двойной индексации, отказ от вспомогательных функций etc. В этой же задаче отказ от двойной индексации вылился бы в боль при реализации перемещения квадратика, может быть это и спасло бы
Как-то на CodeForces было предложение ввести коэффициенты для различных языков, но было принято решение этого не делать, т. к. у каждого языка есть свои плюсы и минусы и участник должен это учитывать.
Понятна позиция. Пожалуй соглашусь. А насчет numpy нет обсуждения? Насколько я знаю, самая оптимальная реализация массивов и всякой математики именно там, а использовать эту библиотеку нельзя
Я обсуждений не видел.
Моя мысли на этот счёт: языки C++ и Java являются де-факто "стандартными" в олимпиадах высокого уровня (в основном это идёт с ACM ICPC). В numpy помимо массивов есть ещё огромное количество всяческих полезностей, вроде линейной алгебры, быстрого преобразования Фурье, очень быстрого перемножения матриц и так далее. Это может дать очень существенное преимущество в некоторых задачах, более того — некоторые задачи таким образом можно будет сдать не тем методом, которые предполагали авторы. Скажем, свести какую-нибудь задачу к умножению матриц и подставить в numpy вместо того, чтобы честно придумывать какую-нибудь оптимизацию в динамике или смотреть на внутренность задачи. Наверняка внутри numpy есть ещё много чего, и думать при составлении задачи про всё сразу с точки зрения автора задачи довольно запарно. Я бы не стал разрешать numpy — мне кажется, это какой-то ещё более неравномерный перекос будет. Скажем, та же рекурсия на питоне наверняка будет продолжать тормозить.
Есть такое обсуждение.
Если вкратце, используется принцип неиспользования сторонних библиотек, т. е. только то, что есть в языке по умолчанию.
Я привык считать, что питон в 1000 раз медленнее C++. Наверное, для PyPy можно сделать оценку 100. Это ОЧЕНЬ много. Просто катастрофически. Конечно, в теории алгоритм с лучшей асимптотикой на достаточно больших тестах будет быстрее. К сожалению, иногда такие тесты бывают настолько большими, что и оптимальный алгоритм будет работать на них больше сотни лет. Поэтому константный фактор нельзя просто так опускать при рассуждениях. В конце концов, цель же не доказать асимптотику, а сдать задачу.
Соглашусь, нужно изначально оценить сложность и научиться прикидывать константу до выбора языка реализации. Наверное, так и буду поступать. Была мысль, что буду все задачи на питоне писать. Но теперь придется пересмотреть эту мысль и учиться писать быстро на плюсах или джаве. Думаю, что все-таки для pypy соотношение не 100 к 1, а примерно 10 к 1. Это я исхожу из наблюдений к этой задаче, и что все-таки для других задач на графах я таки вкладывалась во время 1.5 секунды и максимальное время на тест было все же не в 100 раз больше максимального времени у среднего решения на плюсах.
Есть такая известная оптимизация: a[i][j] хранить как a[i*m + j]. Но не факт что поможет.
Да, верно, я эту оптимизацию использовала для более простых задач на графы, и это дает ускорение в полтора раза. Решение тех задач не проходило по времени, но благодаря в том числе и замене на такой вид индексации удавалось добиться того, что задачи начали проходить.
Здесь же, когда потребовалось двигать этот квадратик и пересчитывать индексы по внешнему периметру, я поняла, что это будет очень проблематично аккуратно написать задачу с одинарной индексацией.
И даже если можно, то теперь уже непонятно, почему нужно усложнять себе жизнь, если можно особо не заморачиваясь написать точно такой же код на плюсах (возможно, и джаве, судя по тому, что достаточно людей на ней сдали эту задачу) с гарантированным результатом...