Разделите список на четные и нечетные части


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.
анатолиг


Можем ли мы вывести список через запятую?
Оливер

Ответы:



21

Python, 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

Попробуйте онлайн или запустите Test Suite

объяснение

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

Genius! Прекрасный.
Исаак

Подождите, как это работает?
Половина

@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 Ха-ха Я немного боюсь Codegolf, но это было так просто для MATLAB! Спасибо за совет;)
Brain Guider

6

Haskell , 37 байт

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

Попробуйте онлайн!

foldrРекурсивно создает список четные и нечетные список. Добавление элемента к списку обновляется путем добавления его к нечетному списку, вызова нового четного списка и вызова предыдущего четного списка новым нечетным списком. Затем пара [l,r]конкатернируется к l++r.

Спасибо Эрджану Йохансену за сохранение 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(++).
Орджан Йохансен,

5

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

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

Попробуйте онлайн!

Ожидается ввод через сплаттинг, как показано на ссылке TIO.

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

Реквизиты TessellatingHeckler за помощь в игре в гольф и этот вариант.
-2 байта благодаря масси.


Предостережения

Строго говоря, когда вопрос написан, это технически неверно, поскольку PowerShell не имеет понятия «списки» как псевдо-неизменяемые объекты, только массивы или хеш-таблицы (или словари). Итак, я рассматриваю строку вопроса « Использовать наиболее естественное представление для списков, которые есть у вашего языка », как вопрос о массивах, так как это самый близкий PowerShell. Кроме того, выходные данные представляют собой один элемент в строке, поскольку это стандартный способ PowerShell для записи массива. Это означает ввод (0,1,2,3,4)воли 0\r\n2\r\n4\r\n1\r\n3\r\n.


47 байт - $args+ splatting вместо $inputи ,@()*2вместо@(),@()
Mazzy

4

F #, 79 77 56

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

Основано на одном из ответов на Haskell

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


Новейшие технологии, круто!
Анатолий

1
@anatolyg Это funправда?
Конор О'Брайен

Я думаю, что это похоже на код 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
Конор О'Брайен

@ 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

Mathematica, 40 байт

#[[;;;;2]]~Join~If[#=={},#,#[[2;;;;2]]]&

{}[[2;;;;2]] выдаст ошибку.


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

С, 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

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

Вдохновлен ответом Sehnsucht (но не достаточно представителя, чтобы комментировать).

Сопоставляет каждое значение с кортежем, где вторая запись является модулем индекса списка, сортируется по модулю, а затем возвращается к исходному значению.


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

coreutils bash и GNU, 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

гания , 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.