Блог пользователя Petruchcho

Автор Petruchcho, 10 лет назад, По-русски

Доброго времени суток, дорогой CF! Меня зовут Егор и я представляю Samara SAU 1 (Petruchcho, Sinner, Slamur). По старой доброй традиции каждый год участники из нашего универа пишут посты на CF про поездки на четвертьфиналы в Саратов. В этом году я решил совместить этот увлекательный рассказ с рассказом о нашем выступлении в Новосибирске на Всесибирской олимпиаде.

Саратов в этом году не сказать, что смог нас чем-то удивить/порадовать. В прошлом году наша команда в упорной борьбе с Саратовскими командами вырвала 4 место. Как и Teddy Bears в позапрошлом году. Да, да, как и в этом году (Монитор). При этом я бы не стал говорить, что мы были недовольны результатом или организацией. Но вы дочитали до интересного: на контесте у нас возникли java проблемы. А именно мы написали решение с авторской асимптотикой, ухудшив константу примерно в два раза. Получили заслуженный (???) TL, а точнее -16 с TL. Ничего, собственно, необычного для нас не произошло, но, поговорив после контеста с I_love_natalia, мы почувствовали, что не все так очевидно. На разборе MikeMirzayanov прогнал наше решение и сказал, что оно отработало за 8.8с вместо 6. Стоит сказать, что хотя эта задача фактически ничего для нас не решала, но неприятное ощущение осталось.

Через неделю мы полетели в Новосибирск. Если кто-то не знает, Всесибирская олимпиада состоит из двух пятичасовых контестов: по АСМ правилам и некое подобие марафонной задачи. Для любителей поностальгировать /blog/entry/5807 (не, у нас в этом плане все отлично).

В первый день мы вновь столкнулись с java проблемами, причем гораздо более серьезными. Вы не поверите, но на java решения с асимптотикой порядка O(6*10^8) по одной из задач или даже O(8*10^7) по другой не очень хорошо упихиваются. При условии, что это авторские решения! Мы за счет огромного опыта и высокого рейтинга все-таки справились с этим и вылетелиушли с контеста с 5 сданными задачами. А хотите узнать, как хорошо прошел второй день, когда надо было заоптимизировать перебор по игре "Балда"? К сожалению, нам для тестирования был выдан слишком мощный (???) комп, на котором наше решение укладывалось в отведенные ограничения на макстестах. Это ввело нас в некоторое заблуждение относительно возможностей нашей программы, что само собой привело к проблемам в конце соревнования, а так же к веселому подгону констант MAGIC, MAGIC2, MAGIC3... К слову, мы проиграли лидерам примерно в 10 раз, да.

Собственно, подвожу к главному. lperovskaya, скинь, пожалуйста, фотографии Sinner в майке Саратовского ГУ.

А если серьезно, в последнее время проблем с java все больше. Отписывайтесь в комментах, если у вас есть подобные истории или вы хотите обвинить нашу команду в кривожнеспособности писать хороший код. Спасибо за внимание!

  • Проголосовать: нравится
  • +47
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится
  1. В саратовском четвертьфинале все было нормально с TL, мы сдали эту задачу за 2.5 сек. из 6
  2. На любом контесте, кроме четвертьфинала, NEERC и финала у вас неизбежно будут джавапроблемы, т.к. никто ее не тестит
  3. Ну и марафонские задачи, говорит кэп, на джаве писать не стоит
  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +13 Проголосовать: не нравится

    Замечу, что на CF, где у вас 2.5 секунды, у нас решение работает за 3.3, так что это не совсем корректное сравнение по ТЛ.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится -40 Проголосовать: не нравится

      Ну тогда остается только попросить MikeMirzayanov прогнать наше, ваше и авторское решения на том компьютере, на котором тестились решения во время четвертьфинала. Со скринкастом.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +10 Проголосовать: не нравится

    Java поддерживается почти на всех крупных контестах, ставить TL не менее 2x от решения на Java — всеобщая практика.

    О не "чф-пф-ф": я знаю людей, которые готовили местный отбор на ВКОШП, и по всем задачам (кроме, видимо, A+B) у них были решения на Java. И это несмотря на то, что большая часть участников вообще пишет на паскале.

»
10 лет назад, # |
  Проголосовать: нравится +33 Проголосовать: не нравится

Небольшой оффтопик: кто-нибудь знает, что это такое?

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +18 Проголосовать: не нравится

    Не знаю, как другие, а я предпочту использовать это приспособление в качестве тренажера для пальцев (типа эспандера наоборот). Надеваешь на пальцы и раздвигаешь.
    Хотя я слышал также предложение о штуке, которую надеваешь на руку и вставляешь туда ручки.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +8 Проголосовать: не нравится

      По поводу эспандера — еще можно надевать на пальцы почти до конца и кодить:) Но к этому нужно некоторое время привыкать.

»
10 лет назад, # |
  Проголосовать: нравится +49 Проголосовать: не нравится

Мыши плакали и кололись

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится -32 Проголосовать: не нравится

    Могу сказать то же самое про C++ с его многочисленными возможностями выстрелить себе в ногу.

    Все языки по-своему ущербны :(.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      Честно говоря, всегда не очень понимал, как люди стреляют себе в ногу на С++, решая олимпиадные задачи. В промышленном программировании -- да, верю, 314159 типов умных указателей и неочевидных вещей everywhere, но на контестах всё это ж [почти] не используется, разве нет? На олимпиадах ну за пределы массива можно выйти и не заметить, а что ещё?

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        И ты ни разу не выходил за пределы массива?

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится +107 Проголосовать: не нравится

        Из того, что сразу вспомнилось с контестов:

        if ((a, b)) вместо if (f(a, b)) (опечатка при быстром наборе)
        
        if (a[i < x]) вместо if (a[i] < x) (еще одна опечатка)
        
        if (a[i]) вместо if (a[i][j]) (это мы писали динамику, а потом добавили параметр, но ифы поменяли не везде)
        
        color[v] = 2, когда массив color состоит из bool (это мы написали dfs с пометками 0 и 1, а потом поняли, что граф ориентированный и надо действовать хитрее, вот и печальный итог)
        

        И последнее, которое ловится warning-ами, но все равно напарывались на это:

        for (int i = 0; i < n; ++i) {
          [много строк кода]
          for (int i = 0; i < n; ++i) {
            [какие-то переходы в динамике, где оба индекса по смыслу не встречаются рядом, то есть каждое конкретное выражение a[i][k] выглядит нормально, но в одном месте i используется по смыслу как переменная внешнего цикла, а в другом - как внутреннего]
          }
        }
        

        Добро пожаловать в мир С++!

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится +30 Проголосовать: не нравится

          Зато благодаря восклицаниям "да как оно вообще скомплировалось?!" тренировки становятся не такими скучными:)

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится +3 Проголосовать: не нравится

          Но все эти примеры на int <--> bool conversion, разве это не ловится ворнингами?

          Я помню, как случайно передали вектор в функцию по значению, а не по ссылке. А этот вектор на случайных тестах был маленького размера. Первый тест, который это валил, кажется, имел номер 51. Никто не догадался посмотреть заголовок функции, поэтому весело провели время за оптимизацией довольно объемного кода.

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится -8 Проголосовать: не нравится

          Java: String/StringBuilder Integer/int (сравнение == по ссылке)

          • »
            »
            »
            »
            »
            »
            10 лет назад, # ^ |
            Rev. 4   Проголосовать: нравится -13 Проголосовать: не нравится

            Не ну если вы не отличаете ссылку на объект от примитивного типа ... Вообще тут ранее была вообще речь об ошибках, которые позволяет вам допустить сам язык. В Java единственная "проблема" если только с generics. Никаких UB, арифметики с указателями, не очевидных приведений типов.

            • »
              »
              »
              »
              »
              »
              »
              10 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Так по сути про generics и речь. Авторы языка сделали для сравнения значений и сравнений ссылок -- РАЗНЫХ по сути операций один символ -- что позволяет допустить ошибку.

              Кое-где кто-то юзал String где надо StringBuilder, такие случаи тоже были

              • »
                »
                »
                »
                »
                »
                »
                »
                10 лет назад, # ^ |
                  Проголосовать: нравится +13 Проголосовать: не нравится

                Я про generics имеют ввиду намного более коварные случаи (но не будем сейчас об этом). А вам не кажется, что ссылка в нативе это фактически адрес в памяти, что есть число? Как его ещё сравнивать c другой ссылкой? А вот если хотите сравнивать объекты по этим ссылкам — equals для вас и придумывали. Иногда можно даже объекты сравнивать на == вместо вызова equals, если вы полностью управляете генерацией объектов. Это даёт хороший буст. Ну и меньше работайте с boxed типами, конвертируйте их при первой возможности в примитивы и будет вам счастье, если не хотите учить правила приведения типов в Java.

                StringBuilder ... вы ещё вспомните про Scanner. Речь о том — насколько легко не заметить ошибку в коде, а не сколько есть не оптимизированных вещей в готовой библиотеке. Последние тупо заучиваются и в случае проблем с TL на Java идёт проверка — а не использую ли я что-то медленное.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  10 лет назад, # ^ |
                  Rev. 2   Проголосовать: нравится -34 Проголосовать: не нравится

                  Я понимаю еще, когда красные начинают меня учить, но вы? :)))))

                  А вам не кажется, что ссылка в нативе это фактически адрес в памяти, что есть число?

                  Конечно, кажется. Но еще больше мне кажется, что Java как раз создана для того, чтобы абстрагироваться от таких деталей. Вы про такую вещь, как например, меченые указатели не слышали? Упакованные указатели? Мало ли кто какую JVM юзает? Сравнение ссылок и значений по сути разные операции. В Питоне операция сравнения ссылок называется is, и нет никакой путаницы.

                  Почему ж тогда нельзя и в С++ "тупо заучить" и глупых ошибок не делать?

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  10 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  В Jave косяков нет! Она дана Б-гом через Моисея!

            • »
              »
              »
              »
              »
              »
              »
              10 лет назад, # ^ |
                Проголосовать: нравится +5 Проголосовать: не нравится

              приведение типа long => double теряет точность и как бы некомильфо(впрочем, в С/С++ тоже так). у double мантисса короче.

          • »
            »
            »
            »
            »
            »
            10 лет назад, # ^ |
              Проголосовать: нравится +5 Проголосовать: не нравится

            Нормальные IDE это подсвечивают желтым.

»
10 лет назад, # |
Rev. 4   Проголосовать: нравится +21 Проголосовать: не нравится

На последнем opencup раунде ( GP of Siberia) (Я так понимаю, он совпадает с финалом всесибирской олимпиады) задача 8(Colonization) на jave за O(N^2*logN) у меня не проходила (TL),а переписанная на С++ проходила.

Java: http://pastie.org/private/kfkqtsht6ucyhpqofihiag

C++: http://pastie.org/private/c226fxlretljj56q7tsxg

И случай, когда переписать на С++ помогает, у меня не первый.

На Кыргызстанском четвертьфинале мы по крайней мере пытаемся делать, чтобы авторские решения на Jave проходили примерно за половину TL. А есть ли такая практика на других олимпиадах?

  • »
    »
    10 лет назад, # ^ |
    Rev. 4   Проголосовать: нравится +8 Проголосовать: не нравится

    Два совета:

    1) Пишите аккуратнее :)

    Достаточно поправить компаратор на однострочный.

    2) Пишите на Яндекс.Контесте

    Вот такой код уже заходит на всех компиляторах на Яндекс.Контесте с запасом в ~1 секунду: http://pastie.org/private/hggubfrboyesui0g1inzsw

    И не заходит ни на каком на ejudge.

    • »
      »
      »
      10 лет назад, # ^ |
      Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится

      Спасибо! Мне почему-то нравится писать компаратор, который возвращает 0 для равных (согласно equals) объектов. Оказывается, это только рекомендуется, но не требуется в данном случае.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится -38 Проголосовать: не нравится

    На топкодере, вроде бы, есть правило, что авторское решение на Java должно работать не более 1 секунды. Возможно, именно наличие этого правила объясняет то, что у Petr на TC рейтинг выше, чем у tourist, а на Codeforces, где такого правила нет, наоборот.

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +5 Проголосовать: не нравится

      а что, на CF есть такое правило? Или у вас есть другая гипотеза про разницу в местах Petr/tourist?

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Вообще-то, у нас тоже есть решения на Java для всех задач, в которых TL критичен. И вроде TL не выставляется меньше, чем удвоенное время работы решения на Java. Однако надо понимать, как пишутся эти java-решения.

    У нас нет ни одного человека, который бы реально писал олимпиадные задачи на Java: все пишут на C++. Поэтому авторские решения спокойно, попивая чаёк, сначала пишутся на C++. Потом этот код копипастится в какое-нибудь java-решение задачи прошлых лет и портируется ручками на java. Иногда бывает такое, что человек сразу пишет второе решение на java, однако таких людей недостаточно на все задачи. Естественно, в условиях "попивая чаёк" решение оказывается существенно эффективнее среднего решения участника...

»
10 лет назад, # |
  Проголосовать: нравится -23 Проголосовать: не нравится

Typical Java

»
10 лет назад, # |
  Проголосовать: нравится -13 Проголосовать: не нравится

Проблемы с Java — это проблемы самих участников. Каждый себе выбирает инструмент исходя из своих пожеланий — если предпочитаете удобство (удобная среда разработки, приятный длинный синтаксис) и надежность (сложно "выстрелить себе в ногу"), то пишите на Java, а если предпочитаете скорость, пишите на C++.

А умные люди в такой ситуации комбинируют оба подхода — например, спросите yarrr — он раньше писал почти все задачи на Java, но критичные по времени решения писал на C++.

А жаловаться на злых авторов — это отмазка для бедных.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +27 Проголосовать: не нравится

    я попрошу, в посте нет ни слова жалобы на авторов. Цель поста — внезапно — указать на существование таких проблем и попросить организаторов больших олимпиад относиться к решениям на официальном языке чемпионата мира чуть ответственнее.

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +23 Проголосовать: не нравится

    С того момента, как полная поддержка некоторого языка заявлена (или предполагается "по умолчанию") на соревновании — это и проблема авторов / организаторов.

    В давнем комментарии andrewzta приводится ссылка на правила подготовки командных школьных олимпиад. Кажется, что правила подготовки к студенческим не должны кардинально отличаться. Особое внимание хочется обратить на раздел "Выбор ограничений и написание решений" и слово "естественно" в первом пункте.

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

    Кажется также, что версия компилятора, используемая в тестирующей системе, нередко является маркёром потенциальных проблем. Если она далеко не последняя — то, скорее всего, Java-решения подготовлены способом, подобным описанному чуть выше stgatilov.

    Конечно, есть ещё один путь — например, в школьных олимпиадах есть "дополнительная группа языков", для которой не гарантируется полной поддержки. Но, кажется, по этому пути по отношению к одному из языков официальных ACM-соревнований идти всё-таки странно (даже на турнире ICL с относительно недавних пор поддерживается Java, хотя и 1.6...)

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +2 Проголосовать: не нравится

    Умные люди комбинируют оба подхода, но при этом задачи, в которых приходится заниматься пиханием, вызывают у них поток нецензурных слов в адрес авторов.

    Другой вопрос: а что мешает людям, занимающимся подготовкой задач, выучить Java на уровне естественного для этого языка написания кода?

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      а почему только Java? Почему не хаскель, или там, D?

»
10 лет назад, # |
  Проголосовать: нравится +61 Проголосовать: не нравится

с асимптотикой порядка O(6*10^8) по одной из задач или даже O(8*10^7) по другой

Ой, пожалуйста, не надо так писать, не путайте асимптотику с количеством операций.

»
10 лет назад, # |
  Проголосовать: нравится +80 Проголосовать: не нравится

У меня подобных проблем было оргомное количество (с тех пор как перешёл на Java). В основном причина простая: авторы пишут решение на C++, а потом поднимают ограничения, чтобы их решение влезало с запасом 2-3x; зачастую этого недостаточно даже для менее оптимально написанных решений на C++, не говоря уж о Java.

Проблема решается очень просто — надо не ставить ограничения и ТЛ впритык по авторскому решению, а пытаться отделить правильное решение от неправильных. Обычно зазор 100x и больше, и отделяется легко (ставим ТЛ 10x от авторского решения, тогда неоптимально написанные правильные решения заходят, а оптимально написанные неправильные — не заходят).

Если же зазор между правильным и неправильным решениями меньше 4x — то стоит задуматься, давать ли вообще такую задачу. Лажу с адскими оптимизациями почти наверняка загонят, а вот у многих участников с нормальным решением будет адское упихивание в ТЛ; такая задача только добавит рандома в результаты и испортит многим участникам впечатление от контеста.