Згорнути сусідні дублікати


22

Виклик

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

Зауважте, що якщо у вас пробіжка непарної довжини рівних чисел, одна з них залишиться, не входячи в пару.

Приклад:

[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0]

По- перше, ви повинні видалити 0, 0, 4, 4і 1, 1отримати:

[0, 1, 2, 2, 0]

Тепер слід видалити 2, 2:

[0, 1, 0]

І це кінцевий результат.

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

[] -> []
[1] -> [1]
[1, 1] -> []
[1, 2] -> [1, 2]
[11, 11, 11] -> [11]
[1, 22, 1] -> [1, 22, 1]
[-31, 46, -31, 46] -> [-31, 46, -31, 46]
[1, 0, 0, 1] -> []
[5, 3, 10, 10, 5] -> [5, 3, 5]
[5, 3, 3, 3, 5] -> [5, 3, 5]
[0, -2, 4, 4, -2, 0] -> []
[0, 2, -14, -14, 2, 0, -1] -> [-1]
[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0] -> [0, 1, 0]
[3, 5, 4, 4, 8, 26, 26, 8, 5] -> [3]
[-89, 89, -87, -8, 8, 88] -> [-89, 89, -87, -8, 8, 88]

Оцінка балів

Це , тому найкоротша відповідь на кожній мові виграє!


Пісочниця для тих, хто може бачити видалені дописи
musicman523

Не має значення, всі вони рівні. Сенс цієї фрази полягає в тому, що [14, 14, 14]згортається на[14]
musicman523

Непрочитайте виклик, вибачте. Думав, що вам доведеться видалити всі пари чисел, що збільшуються на 1 ( 1,2, 11,12і т.д.)
Stephen

Чи можемо ми прийняти введення як розмежуваний рядок?
Shaggy

2
Чи можете ви додати тестовий випадок, наприклад -89,89,-87,-8,-88? І моє (неопубліковане) рішення Japt, і рішення Сітківки Фрі там не виходять, виводячи --87,8.
Кудлатий

Відповіді:


5

Желе , 10 байт

Œgœ^/€FµÐL

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

Як це працює

Œgœ^/€FµÐL  Main link. Argument: A (array)

       µ    Combine all links to the left into a chain.
Œg              Group all adjacent equal items.
    /€          Reduce each group by...
  œ^                symmetric multiset difference.
                In each step, this maps ([], n) to [n] and ([n], n) to [], so the
                group is left with a single item if its length is odd, and no items
                at all if its length if even.
      F         Flatten the resulting array of singleton and empty arrays.
        ÐL  Apply the chain until the results are no longer unique. Return the last
            unique result.

Якщо замість цього використовувати F, ви також створите списки підтримки у своєму списку.
Ерік Аутгольфер

Ні, тут œ^покладається на просування цілого масиву в масив. Оскільки 1D масиви не просуваються до 2D масивів, він не працюватиме ні для чого, крім масиву чисел.
Денніс

Хе ... я маю на увазі, що ти міг би просто використати ŒgWẎ$œ^/$€ẎµÐL... о, чекайте, це занадто наївно. : P
Erik the Outgolfer

4

Сітківка ,17 15 байт

+m`^(.+)¶\1$¶?

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

Збережено 2 байти завдяки Нілу та Мартіну!

Кожна пара чисел замінює нічим. Цей процес циклічно, поки не буде внесено змін.


Розробив ідентичне рішення в Japt, перш ніж помітити це. На жаль, ми обидва не вдається на таких входах, як -89 89 -87 -88 -88, який виводить --87.
Shaggy

1
@Shaggy Спасибі, я виправив це, додавши граничну перевірку та використовуючи _для позначення негативів, як це часто в деяких мовах.
FryAmTheEggman

З того часу я виявив, що це також не вдасться _89 89 _87 _8 _88, вивівши _89 89 _87 8. Вибачте: \
Shaggy

@Shaggy Не шкодуй! Дякуємо, що знайшли проблему! Я додав ще одну граничну перевірку, щоб виправити цю справу.
FryAmTheEggman

1
@FryAmTheEggman Не впевнений, чи мав на увазі Ніл, але ви також можете використати mдля перетворення \bs в ^і $.
Мартін Ендер

3

Mathematica 29 байт

Це неодноразово видаляє пари рівних сусідніх елементів, a_,a_поки не залишиться жодного.

#//.{b___,a_,a_,c___}:>{b,c}&

3

Python 2 , 57 байт

r=[]
for x in input():r+=x,;r[-2:]*=r[-2:-1]!=[x]
print r

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

Ітеративно будує список вихідних даних, додаючи наступний елемент, потім відсікаючи кінець, якщо додаючий елемент дорівнює тому, що передує йому. Перевірка елемента "другий-останній" r[-2:-1]!=[x]виявляється незручним, оскільки можливо, що список має довжину лише 1.



2

Желе , 15 байт

Œr;ṪḂ$$€x/€FµÐL

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

Пояснення

Œr;ṪḂ$$€x/€FµÐL  Main Link
Œr               Run-length encode
  ;              Concatenate (?)
       €         For each element
   ṪḂ$$          Is the last element odd?
          €      For each element    // Non-breaking alternative
        x/       Reduce by repeating // for run-length decode
           F     Flatten
            µ    (New monadic link)
             ÐL  Repeat until results are no longer unique

-1 байт завдяки милям і виправлено :)


Виправлено @FryAmTheEggman; Спасибі!
HyperNeutrino

Я не впевнений, якщо викинути помилку і залишити вихід порожнім, вважається правильним рішенням. Ви програмуєте кидки ValueError: not enough values to unpack (expected 2, got 0)для тестового випадку [1,2,2,1]. Також зауважте, що порожній вихід відрізняється від []та 2відрізняється від [2].

13 байт с Œr;ṪḂ$$€ŒṙµÐL. Щоб уникнути помилки, замініть Œṙна, x/€Fоскільки декодування довжиною запуску видає помилку, коли їй надано порожній список. Щоб побачити вихід у вигляді списку, позначка ŒṘпокаже його.
милі

@ThePirateBay Jelly представлення порожнього списку - порожнє, одного елемента - саме цього елемента, а декількох елементів - списку, розділеного скобами і розділеного комами. Подання має посилання (функцію), а не повну програму (подібно до того, що лямбда буде в Python) - щоб побачити більш "нормальне" місце перегляду ÇŒṘв нижньому колонтитулі, щоб зателефонувати останнє посилання ( Ç) та роздрукувати представлення Python ( ŒṘ) . Однак помилка може бути неприйнятною.
Джонатан Аллан

@JonathanAllan. Гаразд, я зрозумів, що рядкове представлення списку Jelly є прийнятним. Основний пункт мого першого коментаря - зазначити, що помилка видається, коли список стає порожнім.

2

JavaScript (ES6), 54 53 байти

Збережено 1 байт завдяки @ThePirateBay

f=a=>1/a.find(q=>q==a[++i],i=-2)?f(a,a.splice(i,2)):a

Наївне рекурсивне рішення, може бути неймовірним.


Ви можете перевірити поточний і попередній елемент замість поточного і наступного, так що ви можете замінити i=0з i=-2і i-1з iякої дорівнює -1 байт в цілому.

@ guest44851 Дякую, але ... чи це не означає, що мені потрібно змінити це i+1? (Я раніше спробував це з переміщенням ++, а також не зміг розібратися, хоча у мене було лише хвилину на це)
ETHproductions

Ви можете бачити, що вона працює правильно .

@ThePirateBay Добре, ти маєш рацію! Але як?
ETHproductions

2

Python 2 , 73 байти

Оскільки у мене недостатньо репутації для коментарів: я просто змінив відповідь @officialaimm на використання r! = [] Замість len (r), щоб зберегти байт. Дуже розумне рішення для вас, @officialaimm!

r=[]                            # create list that will hold final results. A new list is important because it needs to be removable.
for i in input():               
 if r!=[]and r[-1]==i:r.pop()   # Ensure that we have at least 1 char added to the list (r!=[])... or that the last character of our final result isn't the current character being scanned. If that is, well, remove it from the final list because we do not want it anymore
 else:r+=[i]                    # Shorthand for r.append(i). This adds i to the final result
print r

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

Знову ж таки, занадто пізно ... чому я навіть досі встав?



2

MATL , 7 байт

t"Y'oY"

Для деяких тестових випадків, коли результат порожній, програма виходить із помилкою, але в будь-якому випадку вона дає правильний (порожній) вихід.

Спробуйте в Інтернеті! Або перевірити тестові випадки з порожнім виходом .

Пояснення

t     % Implicit input. Duplicate
"     % For each (i.e. do as many times as input size)
  Y'  %   Run-length encode. Gives array of values and array of run lengths
  o   %   Parity, element-wise. Reduces run-lengths to either 0 or 1
  Y"  %   Run-length decode. Gives array of values appearing 0 or 1 times;
      %   that is, removes pairs of consecutive values
      % Implicit end. Implicit display

Розглянемо вхід

0 0 0 1 2 4 4 2 1 1 0

Кожна ітерація видаляє пари послідовних пар. Перша ітерація зменшує масив до

0 1 2 2 0

Два значення 2, які зараз суміжні, не були суміжними в початковому масиві. Ось чому потрібна друга ітерація, яка дає:

0 1 0

Подальші ітерації залишать це незмінним. Кількість необхідних ітерацій є верхньою межею вхідного розміру.

Порожній проміжний результат призводить Y"до помилки функції декодування довжини ( ) пробігу в поточній версії мови; але вихід, як потрібно, порожній.


Чи можете ви додати пояснення? Мені хотілося б зрозуміти, як ти так міцно бив мене. : P
Денніс

@Dennis Sure! Я забув. Готово :-)
Луїс Мендо

1
Ах, RLE штовхає два масиви. Це корисно.
Денніс

2

машинний код x86 (32-бітний захищений режим), 36 байт

52
8B 12
8D 44 91 FC
8B F9
8D 71 04
3B F0
77 10
A7
75 F9
83 EF 04
4A
4A
A5
3B F8
75 FB
97
EB E7
58
89 10
C3

Вищеописані байти машинного коду визначають функцію, яка приймає масив як вхідний, згортає сусідні дублікати на місці та повертається до абонента, не повертаючи результат. Він слідує __fastcallумові виклику , передаючи два параметри в ECXіEDX регістрів.

Перший параметр ( ECX) - вказівник на перший елемент масиву 32-бітних цілих чисел (якщо масив порожній, він може вказувати кудись у пам'яті). Другий параметр (EDX ) - вказівник на 32-бітове ціле число, яке містить довжину масиву.

Функція змінить елементи масиву на місці, якщо необхідно, а також оновить довжину, щоб вказати нову довжину згорнутого масиву. Це трохи незвичайний метод прийому вводу та повернення виводу, але у вас дійсно немає іншого вибору в мові складання. Як і в C, масиви фактично представлені в мові як вказівник на перший елемент і довжину . Єдине, що тут трохи дивно - це взяти довжину за посиланням , але якби ми цього не зробили, не було б способу скоротити масив. Код буде добре працювати, але вихід міститиме сміття, оскільки абонент не знатиме, де зупинити друк елементів із згорнутого масиву.

Невикольована збірна мнемоніка:

; void __fastcall CollapseAdjacentDuplicates(int * ptrArray, int * ptrLength);
; ECX = ptrArray              ; ECX = fixed ptr to first element
; EDX = ptrLength
   push  edx                  ; save pointer to the length
   mov   edx, [edx]           ; EDX = actual length of the array
   lea   eax, [ecx+edx*4-4]   ; EAX = fixed ptr to last element 

FindAdjacentPairs:
   mov   edi, ecx             ; EDI = ptr to element A
   lea   esi, [ecx+4]         ; ESI = ptr to element B
FindNext:
   cmp   esi, eax             ; is ptr to element B at end?
   ja    Finished             ; if we've reached the end, we're finished
   cmpsd                      ; compare DWORDs at ESI and EDI, set flags, and increment both by 4
   jne   FindNext             ; keep looping if this is not a pair

; Found an adjacent pair, so remove it from the array.
   sub   edi, 4               ; undo increment of EDI so it points at element A
   dec   edx                  ; decrease length of the array by 2
   dec   edx                  ;  (two 1-byte DECs are shorter than one 3-byte SUB)
RemoveAdjacentPair:
   movsd                      ; move DWORD at ESI to EDI, and increment both by 4
   cmp   edi, eax             ; have we reached the end?
   jne   RemoveAdjacentPair   ; keep going until we've reached the end
   xchg  eax, edi             ; set new end by updating fixed ptr to last element
   jmp   FindAdjacentPairs    ; restart search for adjacent pairs from beginning

Finished:
   pop   eax                  ; retrieve pointer to the length
   mov   [eax], edx           ; update length for caller
   ret

На реалізацію надихнула моя відповідь C ++ 11 , але ретельно переписана в зборах, оптимізуючи для розміру. Збірка - набагато краща мова для гольфу. :-)

Примітка: Оскільки цей код використовує рядкові інструкції, є чи припустити , що прапор напрямки ясно ( DF== 0). Це обгрунтоване припущення в більшості операційних середовищ, оскільки ABI, як правило, вимагає, щоб DF був зрозумілим. Якщо цього не можна гарантувати, то в верхній частині коду потрібно вставити 1-байтну CLDінструкцію ( 0xFC).

Крім того, як зазначалося, він передбачає 32-бітний захищений режим, зокрема, "плоску" модель пам'яті, де додатковий сегмент ( ES) такий же, як сегмент даних ( DS).


1

Пакетна, 133 байт

@set s=.
:l
@if "%1"=="%2" (shift/1)else set s=%s% %1
@shift/1
@if not "%1"=="" goto l
@if not "%s:~2%"=="%*" %0%s:~1%
@echo(%*

Я встановлюю s, .тому що Batch плутається, якщо є лише дублікати. Я також повинен використовувати, shift/1щоб я міг %0%s:~1%встановити список аргументів на новий масив і цикл.


Я повинен запитати ... чому? Гарна відповідь ... але чому?
Zacharý

@ Zacharý Тому що там.
Ніл

1
@ Zacharý Частково, вагомий привід для гри в гольф на мовах, що не займаються гольфом, полягає в тому, що це насправді може бути корисним . Ніхто не збирається запускати інтерпретатора Jelly у реальному житті, щоб це зробити, але вони, можливо, знадобляться у пакетному файлі!
Коді Грей

Ой. що має сенс.
Zacharý

1

Желе , 12 байт

ŒgṁLḂ$$€ẎµÐL

Монадійне посилання, що приймає та повертає списки чисел.

Спробуйте в Інтернеті! або побачити тестовий набір

Як?

ŒgṁLḂ$$€ẎµÐL - Link: list
         µÐL - perform the chain to the left until no changes occur:
Œg           -   group runs (yield a list of lists of non-zero-length equal runs)
      $€     -   last two links as a monad for €ach run:
     $       -     last two links as a monad:
   L         -       length (of the run)
    Ḃ        -       modulo 2 (1 if odd, 0 if even)
  ṁ          -     mould (the run) like (1 or 0) (yields a list of length 1 or 0 lists)
        Ẏ    -   tighten (make the list of lists into a single list)

ṁLḂ$$€є еквівалентом, ḣLḂ$$€який є еквівалентом, ṫḊ¿€3$який ви можете замінити ṫḊ¿€3тут, щоб утворити пару / діад.
Ерік Аутгольфер

Це не працює, наприклад, з входом із пробігом довжини 4. Який вхід до декею при кожній ітерації циклу while?
Джонатан Аллан

Ви повинні залишити список із 0 або 1 елементами. Якщо len (x) == 1, то повернеться, []тоді як len (x) == 0 повернеться 0, обидва - фальшиві значення. Вхід до , звичайно, є поточним значенням і матиме поточне значення як лівий аргумент і 3як правий. Якщо len (x) == 4, то це було б те саме, що ṫ3ṫ3або ṫ5залишати вас [].
Ерік Аутгольфер

Я бачу, що це має робити, але чи є xу вашому описі дійсно поточне значення? Спробуйте це для розміру.
Джонатан Аллан

Якщо чесно, я не знаю, чи це код чи помилка :)
Джонатан Аллан


1

05AB1E , 15 байт

[γʒgÉ}€нÐγ‚€gË#

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

Пояснення

[γʒgÉ}€нÐγ‚€gË#
[               # Start infinite loop
 γ              # Group Array into consecutive equal elements
  ʒgÉ}          # Keep the subarrays with an uneven amount of elements
      €н        # Keep only the first element of each subarray
        Ð       # Triplicate the result on the stack
         γ      # Group the top element into consecutive equal elements
          ‚     # Wrap the top two items of the stack in an array
           €g   # Get the length of each subarray
             Ë# # Break if they are equal
                # Implicit print          



1

Python 2 , 74 70 66 байт

  • Дякую @SteamyRoot за 4 байти: rзамість цього len(r)достатньо, щоб перевірити порожнечу списку / стека.
  • Дякую @ovs за 4 байти: краще за умови [i]==r[-1:]

Python 2 , 66 байт

r=[]
for i in input():
 if[i]==r[-1:]:r.pop()
 else:r+=[i]
print r

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


1
Якщо мета len(r)- просто перевірити, чи список порожній чи ні, ви можете мати можливість замінити його просто r, я думаю?
SteamyRoot

О так, спасибі
officialaimm


@ovs Дякую велике, це приголомшливо! (У)
officialaimm

1
Альтернативна версія 66 байт , хоча вимагає лише трьох рядків.
Джонатан Фрех

0

Clojure, 100 байт

#(loop[i % j[]](if(= i j)i(recur(mapcat(fn[p](repeat(mod(count p)2)(last p)))(partition-by + i))i)))

Не впевнений, чи це найкоротше.


0

Баш, 82 байти

cat>b
while cat b>a
perl -pe 's/(\d+) \1( |$)//g' a>b
! diff a b>c
do :
done
cat a

Напевно, є вихід з усіх цих cat, але я цього не знаю.



0

PHP, 81 байт

    function f(&$a){for($i=count($a);--$i;)$a[$i]-$a[$i-1]||array_splice($a,$i-1,2);}

функція, виклик за посиланням або спробувати його в Інтернеті .

не вдається порожній вхід; вставити $i&&або $a&&перед тим, --$iяк виправити.


0

V , 10 байт

òͨ.«©î±î*

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

Стиснутий Regex: :%s/\(.\+\)\n\1\n*. Необов’язковий новий рядок є таким, що він також працює в кінці файлу. Якщо я припускаю, що після закінчення є новий рядок, це буде 8 байт ... але це здається розтяжкою


0

постійного струму , 84 78 байт

[L.ly1-dsy0<A]sA[LtLtS.ly1+sy]sP[dStrdStr!=Pz1<O]sO[0syzdsz1<Oly0<Azlz>M]dsMxf

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

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

  • [0syzdsz1<Olydsx0<Alx1+lz>M]dsMxfОсновний макрос Mскидає лічильник yдо 0, витягує кількість елементів у стеку, зберігає його в регістрі z, а потім запускає макрос, Oякщо в стеку є щонайменше два елементи. Після Oзавершення він завантажує лічильник yі копіює його в реєстр, xперш ніж перевірити, щоб переконатися, що yце ненульовий (тобто стек .має дані). Якщо це так, він запускає макрос A. Нарешті він перевіряє, чи є вихідний розмір стека більше, ніж поточний розмір стека, і відновлює себе, якщо так. Після закінчення він друкує стекf .
  • [dStrdStr!=Pz1<O]sOМакрос Oтимчасово зберігає два верхні елементи в стеку в стек t. Потім вона порівнює два перших пункту та запускає макросP якщо вони не рівні. Нарешті він перевіряє, чи є принаймні два елементи на стеку, і запускається сам, якщо так.
  • [LtLtS.ly1+sy]sPМакрос Pвиймає два елементи із стека t, верхній повертає назад на основний стек і висуває наступний на стек .. Потім він збільшує лічильник y.
  • [L.ly1-dsy0<A]sAМакрос Aбере стек .і перетворює його назад в основний стек. Це робиться так, декрементуючи лічильник, yпоки не залишається нічого, як натиснути.

Відредаговано для пояснення, і для гольфу на 6 байт, оскільки я непотрібно зберігав розмір стека.


0

C ++ 11, 161 байт

#include<vector>
#include<algorithm>
using V=std::vector<int>;void f(V&v){V::iterator i;while((i=std::adjacent_find(v.begin(),v.end()))!=v.end())v.erase(i,i+2);}

Вищевказаний код визначає функцію, fяка приймає std::vector<int>посилання, модифікує її на місці, щоб згортати сусідні дублікати відповідно до специфікації, а потім повертає.

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

Перш ніж перевірити кількість байтів, я подумав, що це досить svelte-код. Більше 150 байт, однак, не так добре! Або я не дуже хороший в гольфі, або C ++ - не дуже гарна мова в гольфі ...

Безголівки:

#include <vector>
#include <algorithm>

using V = std::vector<int>;

void f(V& v)
{
   V::iterator i;

   // Use std::adjacent_find to search the entire vector for adjacent duplicate elements.
   // If an adjacent pair is found, this returns an iterator to the first element of the
   // pair so that we can erase it. Otherwise, it returns v.end(), and we stop.
   while ((i=std::adjacent_find(v.begin(), v.end())) != v.end())
   {
        v.erase(i, i+2);   // erase this adjacent pair
   }
}

C ++ - не найкраща мова для гольфу. Приємного використання std::adjacent_find! Цікаво , якщо ви реалізуєте цю функцію самостійно , якщо вона буде коротше, так як ви можете видалити , #include <algorithm>а також
musicman523

@ Musicman523 Моя перша спроба дійсно здійснити його вручну, хоча я використовував трохи інший алгоритм. Я адаптував реалізацію, std::uniqueщоб робити те, що мені потрібно. Але потрібно багато коду, щоб виконати всю логіку, і коли я трапився впоперек std::adjacent_find, було цілком очевидно, що це переможець з точки зору розміру коду.
Коді Грей





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