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

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

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


На C++ это я бы сделал так: дорожка будет храниться в виде pair <int, int>, где поле first будет равно скорости перемещения по дорожке, поле second будет равно длине дорожки, дальше заводим массив или вектор типа pair <int, int> и стандартная сортировка как раз отсортирует по возрастанию поля first.

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

Оказалось, можно делать так (конечно, для некоторых это не откровение, но я так не делал никогда). Заведем список из номеров дорожек, т.е. просто список [0, 1, 2, ...]:
Idx = list(range(n + 1))
Также заведем два словаря (dict) V и L, которые будут по ключу (номеру дорожки) возвращать ее скорость и длину. Словари заполняются при считывании данных. А дальше - пишем так:
Idx = sorted(Idx, key = V.get)
То есть вызывается стандартная сортировка для списка Idx, но в качестве ключа передается метод get списка V, который по числу (номеру дорожки) будет возвращать скорость ее движения. В результате список номеров Idx будет отсортирован по возрастанию значения V.get(k) (где k - номер дорожки).

А при чем тут ЕГЭ по информатике? А при том, что в этом году на ЕГЭ по информатике была задача C4, где нужно было сделать что-то подобное. Один (неизвестный мне) московский школьник, написал решение на питоне с таким фокусом. Участвуя в проверке работ неделю назад, я увидел это решение, разобрался в нем и теперь смог увиденный в работе школьника прием использовать при решении задачек Code Jam.

Мораль: ЕГЭ может быть полезно не только школьникам, но и проверяющим работы :)

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

15 лет назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

Нда, похоже, что люди, способные просто написать qsort, скоро исчезнут с лица Земли...

  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Да нет, я способен написать qsort и регулярно рассказываю школьникам, как его писать.
    Но зачем на контесте писать qsort, если есть встроенная быстрая сортировка?
    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится -8 Проголосовать: не нравится
      Я верю, что способны, но ход мысли интересен. А, если бы не было того школьника, Вы бы на контесте обдумывали как приспособить встроенную сортировку, или просто написали qsort?  
      • 15 лет назад, скрыть # ^ |
         
        Проголосовать: нравится +3 Проголосовать: не нравится
        Контест - это штука довольно напряженная и нервная, поэтому я не берусь предсказывать, как я повел бы себя на контесте, это довольно непредсказуемо.

        Думаю, что написал бы квадратичную сортировку (а чем я хуже Гены? Гена написал сортировку выбором...), и сделал бы стресс-тест, т.к. не уверен, что на питоне квадратичная сортировка для 1000 элементов отработает быстро.
    • 15 лет назад, скрыть # ^ |
       
      Проголосовать: нравится -15 Проголосовать: не нравится
      Зачем на контесте использовать Python и изобретать велосипед, когда есть гораздо более подходящие C++ и Java?
      • 15 лет назад, скрыть # ^ |
        ← Rev. 4  
        Проголосовать: нравится 0 Проголосовать: не нравится

        Давайте сравним объем кода решения по этой задаче на Питоне и на С++, и потом будем обсуждать, что более подходит - Питон или С++.


        Даже понятно, где его можно немного упростить. Ваше решение на С++ или на Javа будет проще и понятней?


        • 15 лет назад, скрыть # ^ |
           
          Проголосовать: нравится 0 Проголосовать: не нравится
          Спорить не буду, но мне мой код кажется понятней (если что, у меня ник igor.demidov - не нашел, как скопировать ссылку на решение).
          Может, это потому, что я не знаю Python?:)
          • 15 лет назад, скрыть # ^ |
             
            Проголосовать: нравится -11 Проголосовать: не нравится
            В моем решении 689 байт, в вашем - 3339.
            В моем решении 25 строк, в вашем - 118.

            То есть по объему кода мое решение в 4 раза короче, это при том, что алгоритм - одинаковый.

            Так какой же язык более подходит для записи такого решения - Питон или Java?
            • 15 лет назад, скрыть # ^ |
               
              Проголосовать: нравится 0 Проголосовать: не нравится
              Но Вы же понимаете, что класс Pair и методы для считывания данных у меня заранее написаны?

              Впрочем, в этой задаче Python победил. Но вторую Вы ведь писали на C++?
              • 15 лет назад, скрыть # ^ |
                 
                Проголосовать: нравится +6 Проголосовать: не нравится
                Что там у Вас заранее написано, а что не заранее написано - я не знаю. Решение на Питоне - короткое и простое, решение на Java или на C++ в любом случае будет захламлено кучей вещей, далеких от идеи алгоритма, но которые нужны именно для реализации, типа объявления классов и т.д. По моему опыту, запись алгоритма на Питоне всегда проще и понятней, чем на Java или C++.

                Что касается второй задачи - то да, писал на C++. Ибо решение за куб. 5003>108. На C++ - очевидно, пройдет. На Питоне в таких ограничениях - уже вряд ли, в любом случае, лучше не рисковать. Факт, что питон медленный я, конечно, не отрицаю.
            • 15 лет назад, скрыть # ^ |
               
              Проголосовать: нравится -7 Проголосовать: не нравится
              Объем кода ни о чем не говорит. У меня, например, темплейт стандартный на 4 килобайта. Конечно, питон и при написанном хорошем темплейте меньше памяти жрет, но код на плюсах или джавке мне кажется более понятным.
          • 15 лет назад, скрыть # ^ |
            ← Rev. 4  
            Проголосовать: нравится 0 Проголосовать: не нравится

            А как смотреть код на GCJ ?

            UPD: в левом верхнем крае таблицы результатов есть галочка Download Solutions
        • 15 лет назад, скрыть # ^ |
           
          Проголосовать: нравится +2 Проголосовать: не нравится
          Хоть убейте, но мне мое решение кажется проще и для написания, и для понимания
  • 15 лет назад, скрыть # ^ |
    ← Rev. 2  
    Проголосовать: нравится +5 Проголосовать: не нравится

    Я уверен, что Д. П. Кириенко умеет писать быструю сортировку. Другое дело, что на контесте, конечно, быстрее использовать библиотечные функции.
    UPD: бросился защищать преподавателя, не заметив, что тот уже отписался :-)
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    не исчезнут пока мы их готовим :)
15 лет назад, скрыть # |
 
Проголосовать: нравится +13 Проголосовать: не нравится
К слову о парах в C++: по моему так гораздо проще, чем то, что вы сделали:

class pair:
def __init__(self,f,s):
self.first=f;
self.second=s;


a=[pair(1,5),pair(0,3),pair(2,7)]
a.sort(lambda x,y: x.first-y.first);
for i in range(len(a)):
print a[i].first,a[i].second
15 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится
*deleted*
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    1000 ** 2 == 10 ** 6.
    Я остерегаюсь делать 10**6 операций на питоне, хотя здесь, думаю, проблем бы не было.

    Но все равно, пузырек писать сложнее, чем стандартную сортировку :)

15 лет назад, скрыть # |
 
Проголосовать: нравится +6 Проголосовать: не нравится
а зачем все эти велосипеды, если в питоне есть встроенные tuple, sort которых делает ровно то, что надо?
a = []
for i in xrange(n):
   a.append((f(i), i))
print sorted(a)
  • 15 лет назад, скрыть # ^ |
     
    Проголосовать: нравится -8 Проголосовать: не нравится
    Да, я как-то про них не подумал на контесте. Говорю же - никогда такого на питоне не писал.

    Но если честно, мне идея со словарями нравится больше. Вообще, мне очень нравятся словари, они в Питоне очень удобные, поэтому я их часто использую.
15 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

А не то, что получившееся решение вместо О(nlogn)  работает за O(nlog^2n)?
15 лет назад, скрыть # |
← Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Еще там Х до миллиона, так что можно просто разложить дорожки по метрам и сортировать линейный массив.
А так да, массив пар в питоне отлично сортируется. Причем, даже вполне быстро: 10**5 штук проходят на ура.