Від’єднати список


14

Вступ

Більшість із вас знайомі з алгоритмом сортування злиття для сортування списку чисел. Як частина алгоритму, людина пише функцію помічника, mergeяка поєднує два відсортовані списки в один відсортований список. У псевдокоді, подібному Python, функція зазвичай виглядає приблизно так:

function merge(A, B):
  C = []
  while A is not empty or B is not empty:
    if A is empty:
      C.append(B.pop())
    else if B is empty or A[0] ≤ B[0]:
      C.append(A.pop())
    else:
      C.append(B.pop())
  return C

Ідея полягає у тому, щоб постійно з'являти менший з перших елементів Aта Bдо тих пір, поки обидва списки не будуть порожніми, і збирати результати C. Якщо Aі Bобидва сортуються, то так і є C.

І навпаки, якщо Cце відсортований список, і ми розділимо його на будь-які дві піддачі Aі B, тоді Aі будемо Bтакож відсортовані і merge(A, B) == C. Цікаво, що це не обов'язково має місце, якщо Cйого не сортувати, що приводить нас до цього виклику.

Вхідні дані

Ваш вхід - це перестановка перших 2*nнеотримані цілих чисел [0, 1, 2, ..., 2*n-1]для деяких n > 0, поданих у вигляді списку C.

Вихідні дані

Ваш висновок повинен бути значенням truthy , якщо існують два списки Aі Bдовжини nтаких , що C == merge(A, B)і falsy значення в іншому випадку. Оскільки вхід не містить дублікатів, вам не доведеться турбуватися про те, як розриваються зв'язки у mergeфункції.

Правила та бонуси

Ви можете написати або функцію, або повну програму. Виграє найменший байт, а стандартні лазівки заборонені.

Зауважте, що вам не потрібно обчислювати списки Aта Bв екземплярах "так". Однак якщо ви фактично виведете списки, ви отримуєте бонус -20% . Щоб претендувати на цей бонус, потрібно вивести лише одну пару списків, не всі можливості. Щоб полегшити заявку на цей бонус у сильно набраних мовах, дозволено виводити пару порожніх списків в екземплярах "ні".

Брутне форсування не заборонено, але існує бонус у розмірі -10% за обчислення всіх останніх чотирьох тестових випадків загалом менше 1 секунди.

Випробування

В екземплярах "так" подається лише один можливий вихід.

[1,0] -> False
[0,1] -> [0] [1]
[3,2,1,0] -> False
[0,3,2,1] -> False
[0,1,2,3] -> [0,1] [2,3]
[1,4,0,3,2,5] -> False
[4,2,0,5,1,3] -> [4,2,0] [5,1,3]
[3,4,1,2,5,0] -> [4,1,2] [3,5,0]
[6,2,9,3,0,7,5,1,8,4] -> False
[5,7,2,9,6,8,3,4,1,0] -> False
[5,6,0,7,8,1,3,9,2,4] -> [6,0,8,1,3] [5,7,9,2,4]
[5,3,7,0,2,9,1,6,4,8] -> [5,3,7,0,2] [9,1,6,4,8]
[0,6,4,8,7,5,2,3,9,1] -> [8,7,5,2,3] [0,6,4,9,1]
[9,6,10,15,12,13,1,3,8,19,0,16,5,7,17,2,4,11,18,14] -> False
[14,8,12,0,5,4,16,9,17,7,11,1,2,10,18,19,13,15,6,3] -> False
[4,11,5,6,9,14,17,1,3,15,10,12,7,8,0,18,19,2,13,16] -> [4,17,1,3,15,10,12,7,8,0] [11,5,6,9,14,18,19,2,13,16]
[9,4,2,14,7,13,1,16,12,11,3,8,6,15,17,19,0,10,18,5] -> [9,4,2,16,12,11,3,8,6,15] [14,7,13,1,17,19,0,10,18,5]

Відповіді:


3

Pyth, 39 * 0,9 * 0,8 = 28,08

#aY->QxQeS-QsY&YsY)KfqylTlQmsdty_Y%tlKK

Ця програма закріплює всі два бонуси. Він друкує пару списків, якщо можливе скасування об'єднання, інакше порожній список, який є хибним значенням у Pyth (та Python).

Input:  [5,3,7,0,2,9,1,6,4,8]
Output: ([9, 1, 6, 4, 8], [5, 3, 7, 0, 2])
Input:  [5,7,2,9,6,8,3,4,1,0]
Output: [] (falsy value)

Ви можете перевірити його в Інтернеті , але це може бути трохи повільніше, ніж офлайн-версія. Офлайн-версія вирішує кожен тестовий випадок за <0,15 секунди на моєму ноутбуці.

Ймовірно, (один з) вперше, рішення Pyth активно використовує Винятки (це зберегло принаймні 1 знак). Він використовує ту саму ідею, що і рішення Пітера Тейлора.

                         preinitialisations: Q = input(), Y = []
#                 )     while 1: (infinite loop)
        eS-QsY             finds the biggest, not previous used, number
      xQ                   finds the index
    >Q                     all elements from ... to end
   -          &YsY         but remove all used elements
 aY                        append the resulting list to Y

When all numbers are used, finding the biggest number fails, 
throws an exception and the while loop ends.  
This converts [5,3,7,0,2,9,1,6,4,8] to [[9, 1, 6, 4, 8], [7, 0, 2], [5, 3]]

        msdty_Y  combine the lists each for every possible subset of Y (except the empty subset)
 fqylTlQ         and filter them for lists T with 2*len(T) == len(Q)
K                and store them in K

%tlKK        print K[::len(K)-1] (prints first and last if K, else empty list)

Pyth, 30 * 0,9 = 27,0

Я не дуже намагався вирішити це питання, не надрукувавши отримані списки. Але ось швидке рішення, засноване на наведеному вище коді.

#aY->QxQeS-QsY&YsY)fqylsTlQtyY

Я в основному видалив лише заяву про друк. Вихід є досить потворним.

Input:  [0,1,2,3]
Output: [[[3], [2]], [[3], [1]], [[2], [1]], [[3], [0]], [[2], [0]], [[1], [0]]] (truthy value)
Input:  [5,7,2,9,6,8,3,4,1,0]
Output: [] (falsy value)

Спробуйте в Інтернеті .


Ви можете виявити, що замість друку (K[0], Q-K[0])ви можете друкувати (K[0], K[-1]). Я не знаю, чи це дозволило б заощадити.
Пітер Тейлор

@PeterTaylor дякую, врятував 2 символи.
Якубе

@PeterTaylor та ще 2 символи, якщо я друкую K[::len(K)-1].
Якубе

4

GolfScript (35 * 0,9 = 31,5)

{.$-1>/~,)\.}do;]1,\{{1$+}+%}/)2/&,

Онлайн демо досить повільно: на моєму комп'ютері, він запускає всі тести в рамках 0,04 секунди, тому я вимагаю зниження на 10%.

Пояснення

Суфікс C, який починається з найбільшої кількості в C, повинен надходити з того самого списку. Тоді це міркування можна застосувати до (C - суфікс), так що проблема зменшиться до суми підмножини.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.