Розділіть список на парні і неіндексовані частини


26

Натхненний цим питанням:

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

Наприклад:

Вхід: [0, 1, 2, 3, 4]

Вихід: [0, 2, 4, 1, 3]

Інший приклад:

Вхід: [110, 22, 3330, 4444, 55555, 6]

Вихід: [110, 3330, 55555, 22, 4444, 6]

Використовуйте найбільш природне представлення для списків, якими є ваша мова. Обмежень щодо складності немає (наприклад, нормально виділити тимчасовий список - не потрібно робити це на місці).

PS Він повинен працювати для порожнього списку (порожній вхід => порожній вихід).



Чи можна припустити, що всі елементи списку є позитивними чи негативними чи щось таке?
Мартін Ендер

@ MartinBüttner Припустимо що-небудь розумне, можливо навіть те, що вони знаходяться в діапазоні 0 ... 255.
anatolyg


Чи можемо ми вивести список, розділений комами?
Олівер

Відповіді:



21

Пітон, 23 байти

lambda x:x[::2]+x[1::2]

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


1
Чому lambda? Чому ні muчи nu? : P
Kritixi Lithos

1
@rayryeng Я тільки жартував, як ви можете бачити ": P" наприкінці мого коментаря :)
Kritixi Lithos

5
Так, ви напевне повинні замінити lambdaна λі зменшити кількість байт на 5! : P
anatolyg

3
@anatolyg звучить як ідея для подання PEP !
Нік Т

2
@ThomasKwa Це правильний інструмент для роботи: P
Mego

16

Піта, 5

o~!ZQ

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

Пояснення

o~!ZQ    ## implicit: Z = 0; Q = eval(input)
o   Q    ## sort Q using a supplied function
 ~!Z     ## Use the old value of Z, then set Z to be not Z
         ## This assigns a weight to each number in the list, for example given [0,1,2,3,4]
         ## This will give (value, weight) = [(0,0), (1,1), (2,0), (3,1), (4,0)]
         ## The values are sorted by weight and then by index
         ## This happens because Pyth is written in Python, which performs stable sorts

Геніальність! Гарний.
isaacg

Зачекайте, як це працює?
justhalf

@justhalf Я додав ще пояснення, чи це зрозуміло?
FryAmTheEggman

11

CJam, 7 байт

{2/ze_}

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

Перевірте це тут.

Пояснення

Пояснення передбачає, що вершина стека - це масив [0 1 2 3 4]. Фактичні значення не впливають на обчислення.

2/  e# Split the array into chunks of two: [[0 1] [2 3] [4]]
z   e# Zip/transpose, which works on ragged arrays: [[0 2 4] [1 3]]
e_  e# Flatten the result: [0 2 4 1 3]

9

Лабіринт , 28 25 24 23 22 байт

" >
?!?:|}\{@
@\?"":)!

Це була шалена забава! :) Це на сьогоднішній день найбільш густо стисла програма «Лабіринт», про яку я писав. У мене було так багато версій на 20 і 21 байт, які майже працювали, що я все ще сумніваюся, що це оптимально ...

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

Полювання на 20/21 байт: Я перевірив усі програми форми

" XX
?!?X}\{@
@\?XX)!

де Xє будь-який розумний характер грубою силою, але не знайшли жодних дійсних рішень. Звичайно, це не означає, що коротшого рішення не існує, але неможливо змусити 20-байтні програми без гідної кількості припущень щодо його структури.

Пояснення

(Пояснення трохи застаріло, але я все ще не впевнений, що рішення оптимальне, тому я зачекаю з оновленням.)

Отже, зазвичай програми Лабіринту повинні виглядати як лабіринти. Поки покажчик інструкцій знаходиться в коридорі, він буде слідувати цьому коридору. Коли IP потрапляє в будь-який тип з'єднання, напрямок визначається виходячи з верхнього значення основного стеку Лабіринту (Лабіринт має дві стеки, з нескінченною кількістю нулів внизу). Це зазвичай означає, що будь-який нетривіальний цикл буде досить дорогим, тому що якщо у вас є не стінні комірки всюди, все є стиком, і в більшості випадків у верхній частині стека не буде потрібного значення для IP пройти шлях, який ви хотіли б пройти. Отже, ви збільшуєте петлі таким чином, щоб вони мали ціле в центрі, лише одна чітко визначена точка входу та виходу кожна.

Але цього разу мені пощастило, і все так добре поєднувалося, що я міг збити це все на одну велику грудку. :)

Контрольний потік починається на _півдні, що йде. _Штовхає нуль на основний стек. Це може здатися відключеним, але це збільшує глибину (без неявних) стеків, до 1якої нам знадобиться пізніше.

?читає ціле число з STDIN. Якщо немає більше цілих чисел, які слід читати, це натискає нуль. У цьому випадку IP продовжує рухатися на південь і одразу @припиняє програму (оскільки список вводу порожній). В іншому випадку IP перетворюється на Схід.

Зараз ми входимо в дуже щільний цикл з двома точками виходу:

 !?;
 \?
  ;

!друкує ціле число назад до STDOUT, залишаючи лише нуль на стеці. IP продовжує рухатися на Схід і ?зчитує наступне ціле число. Якщо це не нуль, ми беремо право і рухаємося на Південь. ?читає ще один (наступний рівний індекс). Знову ж таки, якщо це не нуль, ми беремо право і рухаємося на Захід.

Потім \друкується передача ліній, не змінюючи стек, тому ми беремо інше праворуч, рухаючись на північ. !друкує наступне парне ціле число. Оскільки зараз на стеці є щонайменше одне ціле (непарне) число непарного індексу, ми продовжуємо повертати праворуч і цикл повторюється.

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

У випадку, якщо в списку був лише один елемент, ми закінчили (тому що ми це надрукували одразу), тож IP буде продовжувати рухатися на Схід до кінця @, знову закінчуючи програму (друкуючи трейлінг на дорозі).

В іншому випадку нам також потрібно буде надрукувати цілі числа непарних індексів. У цьому випадку два контури (від двох точок виходу першого циклу) зливаються посередині ", в обох випадках повертаючи Схід.

_натискає нуль, щоб уникнути ліворуч @, і ;відкидає цей нуль. Тепер ми вводимо новий цикл:

     "}
     ""

IP вводить це в нижній лівій комірці, рухаючись на північ, обходячи петлю за годинниковою стрілкою. }Зрушує верхню частину основного стека до допоміжної стеку. Хоча на стеку ще є елемент, IP продовжує робити все. Після того, як все переміщується в допоміжний стек (і повертається назад у процесі), IP замість цього рухається на Схід, вводячи останній цикл:

       \{@
       #!

\знову друкує передачу ліній, {переміщує елемент із допоміжного стеку назад до основного. Якщо це все-таки було елементом у списку, воно буде позитивним, і IP поверне на південь, де цей пункт друкується !. Потім# натискає глибину стека (і тепер _тут важливо початкове , оскільки це #забезпечує позитивну глибину стека), щоб IP все ще повертався праворуч, через \і {знову.

Після того, як ми надрукували все, {витягне нуль з нижньої частини допоміжного стеку, IP продовжується на схід і @припиняє програму.


8

МАТЛАБ, 24

@(x)x([1:2:end 2:2:end])

схожий на пітон.

Дякуємо @LuisMendo за збереження 2 байтів!


1
Гей! Приємно бачити вас у PPCG!
Луїс Мендо

3
Трохи коротше:@(x)x([1:2:end 2:2:end])
Луїс Мендо

@LuisMendo Haha Я трохи боюся кодегольфа, але це було так просто для MATLAB! Дякую за пораду;)
Brain Guider

6

Хаскелл , 37 байт

concat.foldr(\x[l,r]->[x:r,l])[[],[]]

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

foldrРекурсивно створює список парні і непарні список. Попередження елемента до списку оновлюється, попередньо додавши його до непарного списку та називаючи його новим парним списком, а також попереднім викликом парного списку новим непарним списком. Потім пара [l,r]зв'язана з l++r.

Завдяки Ørjan Johansen за збереження 5 байт, використовуючи двоелементні списки замість кортежів.


42 байти:

f l=[x|p<-[even,odd],(i,x)<-zip[0..]l,p i]

Додає в список індекси lта фільтрує парні чи непарні.


g(a:_:l)=a:(g l)
g l=l
f l=g l++(g$drop 1 l)

Ще один формат, для 44. Функція gприймає кожен рівномірний елемент. Непарні показники отримуються спочатку скиданням елемента, а потім застосуванням g. Якби lгарантовано було не порожньо, ми могли б сміливо робити tailлише 41 рік

g(a:_:l)=a:(g l)
g l=l
f l=g l++g(tail l)

1
ще один варіант (39 байт): l#(a:b:c)=a:(l++[b])#c;l#x=x++l;f=([]#)з fосновною функцією.
німі

@nimi Це приємне рішення, вам слід його опублікувати.
xnor

Ні, будь ласка, включіть його у свій пост. Це просто поєднання ваших №2 та №3.
німі

1
Ви можете зберегти 5 байт у другій версії, використовуючи списки, а concatне кортежі та uncurry(++).
Ørjan Johansen

5

PowerShell v3 +, 75 67 49 47 байт

$l=,@()*2
$args|%{$l[($f=!$f)]+=$_}
$l[0]
$l[1]

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

Очікує введення через бризки, як показано на посиланні TIO.

Створює матрицю $lяк масив масивів, потім передає вхід $argsу цикл |%{}. Кожного разу через цикл ми додаємо елемент до одного з двох дочірніх масивів $l, обертаючи $fзмінну, використовуючи логіку Boolean. Перший раз через, $fє $null, то !з яких $true, або 1при індексації в масив. Це означає, що перший елемент потрапляє у другий масив $l, тож саме тому $l[1]отримує перший вихід.

Реквізити TesselilingHeckler для допомоги в гольфі і цього варіанту.
-2 байти завдяки маззі.


Коваджі

Якщо виходити із запитання, це технічно є недійсним, оскільки PowerShell не має поняття "списки" як псевдонезмінні об'єкти, лише масиви або хеш-таблиці (також словники). Отже, я розглядаю рядок питання " Використовувати найбільш природне представлення для списків, які має ваша мова ", як запитання про масиви, оскільки це найближчий PowerShell. Крім того, вихід - це один елемент на рядок, оскільки це спосіб PowerShell записати масив за замовчуванням. Це означає вхід (0,1,2,3,4)волі 0\r\n2\r\n4\r\n1\r\n3\r\n.


47 байт - $args+ бризки замість цього $inputі ,@()*2замість цього@(),@()
маззи

4

F #, 79 77 56

fun x->List.foldBack(fun x (l,r)->x::r,l)x ([],[])||>(@)

На основі однієї з відповідей Хаскелла

fun x->x|>List.indexed|>List.partition(fst>>(&&&)1>>(=)0)||>(@)|>List.map snd

Спочатку індексуємо список, потім розділяємо його за критеріями: перший елемент (індекс) і додаємо до 1, що дорівнює 0.
Це дає нам список списку пар; Перший список містить усі індексовані евенти, а інший - індекси.
З цього ми збираємо два списки з оператором додавання і, нарешті, відкидаємо індекс.

Редагувати: пропустив очевидний, немає потреби називати аргумент "xs" (звички), тому можна зменшити до 1-літерного імені


У мене також є потенційний 76 байт, який в основному той самий, але визначений як функціональний склад. Проблема в тому, що вона не компілюється як значення, але ефективно працюватиме з будь-яким аргументом списку, поданим настільки невпевнено, якщо це нормально чи ні:

List.indexed>>List.partition(fst>>(&&&)1>>(=)0)>>fun(e,o)->e@o|>List.map snd

Примітка: List.indexed доступний лише з F # 4.0, хоча ще не був задокументований у MSDN


Найсучасніша технологія, класно!
anatolyg

1
@anatolyg Це так fun, чи не так?
Conor O'Brien

Я думаю, це схоже на код Perl 6, який я вперше спробував. -> \xs { xs.pairs.classify( *.key%%2, :as( *.value ) ).map( *.value.Slip ) }Припустимо, що |>в F # приблизно еквівалентно правому оператору корму ==>в Perl 6. Я також лише здогадуюсь, що fst>>(&&&)1>>(=)0робить
Бред Гілберт b2gills

4

JavaScript (ES6), 52 байти

Це також робить це за один прохід

x=>x.map((v,i)=>x[(i*=2)>=(z=x.length)?i-z+--z%2:i])


Ви можете опустити F=з початку; ви можете зберегти байт, скориставшись цим:(i*=2)>=(z=x.length)?i-z+--z%2:i
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Приємна ідея дякую!
Джордж Рейт


3

J, 8 байт

/:0 1$~#

Це монадійне (одноаргументне) дієслово, яке вживається так:

  (/:0 1$~#) 110 22 3330 4444 55555 6
110 3330 55555 22 4444 6

Пояснення

/:        Sort the input array according to
  0 1     the array 0 1
     $~   repeated enough times to be of length
       #  length of input

1
Альтернативою є /:0:`1:\також 8 байт.
милі



2

Бурлеск, 12 байт

J2ENj[-2EN_+

Використання як у:

blsq ) {0 1 2 3 4}J2ENj[-2EN_+
{0 2 4 1 3}
blsq ) {110 22 3330 4444 55555 6}J2ENj[-2EN_+
{110 3330 55555 22 4444 6}

Пояснення:

J     -- duplicate
2EN   -- every 2nd element
j     -- swap
[-    -- tail
2EN   -- every 2nd element
_+    -- concatenate parts

Хоча після виходу нового оновлення ви можете зробити це за допомогою нового вбудованого Unmerge (який робить протилежне **вбудованому злиття ):

blsq ) {110 22 3330 4444 55555 6}J2ENj[-2EN**
{110 22 3330 4444 55555 6}

2

Perl, 35 33 байт

perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'

31 байт + 2 байти для -ap. Читає рядки з обмеженням пробілу від STDIN:

$ echo 0 1 2 3 4 | perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'
0 2 4 1 3

$ echo 110 22 3330 4444 55555 6 | perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'
110 3330 55555 22 4444 6

Коли вхід порожній, друкується єдиний пробіл, який я вважаю еквівалентним порожньому списку. Якщо ні, можна зафіксувати вартістю 4 байти за допомогою:

perl -anE 'push@{$|--},$_ for@F;$,=$";say@0,@1'

(потрібен Perl 5.10+, друкує останній рядок)

або вартістю 5 байт з:

perl -ape 'push@{$|--},$_ for@F;$_=join$",@0,@1'

(відсутнє пробіли)

Як це працює

У цьому рішенні використовується -aпрапор, який розбиває вхід на пробіл і розміщує результати в @Fмасиві.

Справжня магія відбувається в push:

push@{$|--},$_

$|Мінлива зазвичай використовується для примусового виведення гіперемію, але у нього є ще одна цікава властивість: коли декрементируется раз, його значення переключення між 0 і 1.

perl -E 'say $|-- for 0..4'
0
1
0
1
0

Скориставшись тим, що немає обмежень щодо ідентифікаторів, визначених за допомогою символічної перенаправлення , ми по черзі натискаємо елементи масиву на масиви @0та @1масиви, тому @0закінчуємо всі парні елементи та @1коефіцієнти. Тоді ми просто об'єднуємо складні масиви, щоб отримати наш вихід.


2

C, 70

Нічого особливого, лише функція відображення індексу.

a=0;main(int c,int** v){for(c--;a<c;)puts(v[1+a*2%c+!(a++<c/2|c%2)]);}

Менше гольфу

a=0;
main(int c, int** v) {
  for(c--; a<c;)
    puts(v[1 + a*2%c + !(a++ < c/2 | c%2) ]);
}


1

Віци, 22 байт

Віци насправді цього не робив ...

r '' Vl2 / \ [N {VO] l \ [NVO]
r Зворотне значення неявного цифрового стека вводу.
 '' V Збережіть символ "пробіл" як глобальну кінцеву змінну.
     l2 / \ [....] Повторіть матеріал у дужках по довжині вводу
                        стек розділений на 2.
          N {VO Виведіть верхню частину стека як число, а потім змістіть
                        стек один раз ліворуч, просуньте пробіл, виведіть його.
               l \ [...] Для решти стека повторіть це багато разів ...
                  NVO Виведіть верхній елемент стека у вигляді розділеного числа 
                        пробілом.

1

Perl 6 , 25 байт

Це найкоротша лямбда, яку я міг придумати.

{|.[0,2...*],|.[1,3...*]} # 25 byte "Texas" version
{|.[0,2…*],|.[1,3…*]}     # 25 byte "French" version
say {|.[0,2…*],|.[1,3…*]}( ^5 ); # (0 2 4 1 3)␤

say ((0..4),('m'..'q'),(5..9)).map: {|.[0,2…*],|.[1,3…*]}
# ((0 2 4 1 3) (m o q n p) (5 7 9 6 8))␤


# bind it as a lexical sub
my &foo = {|.[0,2…*],|.[1,3…*]}

say foo [110, 22, 3330, 4444, 55555, 6]; # (110 3330 55555 22 4444 6)␤

say [~] foo 'a'..'z' # acegikmoqsuwybdfhjlnprtvxz␤

1

Мінколанг 0,12 , 15 байт

$nI2:[i1+g]r$N.

Спробуйте тут.

Пояснення

$n                 Read in all of input as numbers
  I2:              The length of the stack divided by 2 (n)
     [             Open for loop that repeats n times
      i1+          Loop counter + 1
         g         Gets the (i+1)th item from the stack and puts it on top
          ]        Close for loop
           r       Reverse the stack (for outputting)
            $N.    Output the whole stack as numbers and stop.

1

R, 49 байт

q<-function(x)c(x[seq(x)%%2==1],x[seq(x)%%2==0])

Назвіть це як q (бла). Або якщо x вже містить список, який потрібно переставити, то

c(x[seq(x)%%2==1],x[seq(x)%%2==0])

складає всього 35 байт.


1

F #, 64

fun x->List.mapi(fun i l->l,i%2)x|>List.sortBy snd|>List.map fst

Натхненний відповіддю Шенсухта (але недостатньо реп. Для коментарів).

Кожне значення вказує в кортеж, де другий запис є модулем індексу списку, сортується за модулем, а потім відображається до початкового значення.


1

Пролог, 103 байти

r([E,O|T],[E|A],[O|B]):-r(T,A,B).
r([],[],[]).
r([E],[E],[]).
p(L):-r(L,A,B),append(A,B,X),write(X).

Приклад

>p([1,2,3,4,5]).
[1,3,5,2,4]

1

bash та GNU coreutils, 68 байт

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

(paste - <(seq 0 5 9999)|tee x|grep 0$;grep 5$<x)|cut -f1|grep -v ^$

На жаль, це буде ігнорувати будь-які вхідні дані за межами індексу 1999 року, тому це не зовсім відповідає специфікації.

Він також клобує жорсткий кодований тимчасовий файл ('x'), який може бути проблематичним при паралельному виконанні, і він не видаляє його згодом. Вибач за це!


1

PHP, 78 69 байт

PHP може скидати і зрізати, але не переплітати масиви; що робить це трохи об'ємним:

function(&$a){while($i++<count($a)>>1)$a[]=array_splice($a,$i,1)[0];}

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


перший підхід (програми на 78 байт):

for(;++$i<$argc;)echo",",$argv[$i++];for($i=1;++$i<$argc;)echo",",$argv[$i++];

друкує провідну кому; вставити [!$i]перед першою$argv щоб зняти його.

Два інших 78-байтних рішення (надрукуйте провідну та кінцеву кому):

for($n=$argc-2|1;++$i<$argc*2;)$i&1?print",".$argv[$i]:$argv[$n+=2]=$argv[$i];
for($n=$argc-2;++$i<$argc*2;)$i&1?print",".$argv[$i]:$argv[1|$n+=2]=$argv[$i];

Запустіть php -nr '<code>' <arguments>або спробуйте їх в Інтернеті



0

Clojure / ClojureScript, 52 байти

(defn f[l](flatten(map #(take-nth 2 %)[l(rest l)])))

Написане в ClojureScript REPL, також має бути дійсним Clojure.



0

Hassium , 191 байт

Цей був досить довгий :(
Він читає масив з аргументів, тому запустіть цеhassium file.has 0 1 2 3 4

func main(){a=args;e,o=[]for(c=0;c<a.length;c++)if(c%2==0)e.add(a[c])else o.add(a[c])print("["+(e+o).toString().replace("{", "").replace("}", "").replace("Array", "").replace("  ", "")+"]");}

Запуск і розкриваються з тестом тут

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