将列表分为偶数索引部分和奇数索引部分


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 2015年


我们可以输出逗号分隔的列表吗?
奥利弗

Answers:




16

Pyth,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 2015年

等等,这如何运作?
2015年

@justhalf我添加了更多解释,这可以清除它吗?
FryAmTheEggman 2015年

11

CJam,7个字节

{2/ze_}

压入一个块(最接近未命名函数的块),该块将根据需要转换顶部堆栈元素。

在这里测试。

说明

解释假定堆栈的顶部是array [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遇到任何类型的连接时,将根据Labyrinth主堆栈的最高值来确定方向(Labyrinth有两个堆栈,底部有无限数量的零)。这通常意味着任何非平凡的循环都会非常昂贵,因为如果您到处都是非墙单元,那么所有东西都是结点,并且在大多数情况下,堆栈顶部的IP值不正确走你想走的路。因此,您要做的是放大循环,使它们在中心具有一个整体,每个循环只有一个定义明确的入口和出口点。

但这一次我真的很幸运,一切都很好地融合在一起,以至于我可以将它们压成一团。:)

控制流始于_向南。所述_推零到主堆叠。这看起来像是无操作,但是这增加了(非隐式)堆栈深度1,我们以后需要使用该深度。

?从STDIN读取一个整数。如果没有更多的整数要读取,则将其推为零。在这种情况下,IP继续向南移动并立即@终止程序(因为输入列表为空)。否则,IP向东。

我们现在进入一个非常紧密的循环,有两个出口点:

 !?;
 \?
  ;

!将整数打印回STDOUT,仅在堆栈上保留零。IP继续向东移动,并?读取下一个整数。如果那不是零,我们就向右移动并向南移动。?读取另一个(下一个偶数索引)。再说一次,如果那不是零,我们就向右移动并向西移动。

然后\在不更改堆栈的情况下打印换行符,因此我们向右移,向北移动。!打印下一个偶数索引整数。由于现在堆栈上至少有一个(正)奇数索引整数,因此我们一直向右转,循环重复进行。

一旦其中任何一个?到达列表的末尾,它们便将零推入并直接移至相应的;,从而丢弃该零。

在列表中只有一个元素的情况下,我们已经完成了(因为我们已经立即打印了该元素),所以IP会一直向东移动到@,再次终止程序(打印尾随换行)。

否则,我们还需要打印奇数索引整数。在这种情况下,两条路径(从第一个循环的两个出口点开始)在中间合并",在两种情况下都向东。

_推送零以避免将左移@,并;丢弃该零。现在我们进入一个新循环:

     "}
     ""

IP在左下角的单元格中进入此地址,向北移动,以顺时针方向绕环行。将}主堆栈的顶部移至辅助堆栈。尽管堆栈中仍然有一个元素,但IP仍在继续其工作。一旦一切都转移到辅助堆栈(并在过程中反转),IP继续向东移动,进入最后一个循环:

       \{@
       #!

\再次打印换行符,{将项目从辅助纸叠移回主纸叠。如果那仍然是列表中的一项,它将为正,并且IP转向南(在该处打印该项)!。然后#推入堆栈深度(现在这是初始位置_很重要的位置,因为这#确保了正的堆栈深度),这样IP 便会通过\{再次右移。

在我们打印{完所有内容之后,从辅助堆栈的底部拉零,IP继续向东,并@终止程序。


8

MATLAB,24

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

与python类似。

感谢@LuisMendo节省2个字节!


1
嘿! 很高兴在PPCG见到您!
路易斯·门多

3
短一点:@(x)x([1:2:end 2:2:end])
Luis Mendo

@LuisMendo哈哈我对codegolf有点害怕,但是对于MATLAB来说这很容易!感谢您的提示;)
Brain Guider 2015年

6

Haskell,37个字节

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

在线尝试!

foldr递归地建立了甚至列表和奇数列表。通过将元素添加到列表之前,将其添加到奇数列表,然后将其称为新的偶数列表,然后将之前的偶数列表称为新的奇数列表,即可更新该元素。然后,该对[l,r]被限制为l++r

感谢ØrjanJohansen使用两元素列表代替元组来节省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保证非空,我们可以放心地做tail41

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 2015年

@nimi这是一个不错的解决方案,您应该发布它。
xnor 2015年

不,请在您的帖子中添加它。这只是您的#2和#3的组合。
nimi 2015年

1
您可以使用列表而concat不是元组和来在第二个版本上保存5个字节uncurry(++)
与Orjan约翰森

5

PowerShell v3 +,75 67 49 47字节

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

在线尝试!

期望通过喷溅输入,如TIO链接所示。

将矩阵创建$l为数组数组,然后将输入$args通过管道传递到loop中|%{}。每次循环时,我们都会使用布尔逻辑$l$f变量进行翻转,从而将元素添加到的两个子数组之一中。第一次通过,$f$null,则!其是$true,或1索引到一个数组时。这意味着第一个元素被放入的第二个数组中$l,所以这就是为什么$l[1]要先输出的原因。

TessellatingHeckler提供高尔夫辅助和这种变化的道具。
-2个字节,感谢mazzy。


注意事项

严格按照问题的写作,从技术上讲,这是无效的,因为PowerShell没有将“列表”作为伪不可变对象的概念,仅包含数组或哈希表(又名字典)。因此,我将问题所在的行“ 使用最自然的表示形式用于您的语言所拥有的列表 ”当作询问数组,因为这是最近的PowerShell。此外,输出是每行一个元素,因为这是PowerShell写入数组的默认方式。这意味着将输入(0,1,2,3,4)will输出0\r\n2\r\n4\r\n1\r\n3\r\n


47个字节 - $args+泼洒代替$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
进行和。第一个列表将包含所有索引的偶数,而其他索引的几率。
由此,我们用append运算符重组了两个列表,最后丢弃了索引。

编辑:错过了一个明显的没有必要命名arg“ 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 2015年

我认为这类似于我第一次尝试的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个字节。
2016年

3

果冻,4字节

s2ZF

在线尝试!

根据Martin的CJam答案

s2ZF - Main link. Argument: L (a list) e.g.  [110, 22, 3330, 4444, 55555, 6]
s2   - Split into chunks of length 2         [[110, 22], [3330, 4444], [55555, 6]]
  Z  - Columns                               [[110, 3330, 55555], [22, 4444, 6]]
   F - Flatten                               [110, 3330, 55555, 22, 4444, 6]

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

利用对通过符号解引用指定的标识符没有限制的事实,我们将数组元素交替推入@0and @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

Vitsy,22字节

Vitsy 确实不是这样做的...

r''Vl2 / \ [N {VO] l \ [NVO]
r反转隐式数值输入堆栈。
 ''V将“空格”字符另存为全局最终变量。
     l2 / \ [....]重复括号中输入内容的长度
                        堆栈除以2。
          N {VO将堆栈的顶部项目输出为数字,然后移位
                        将堆栈移到左侧一次,推动一个空格,然后输出。
               l \ [...]对于堆栈的其余部分,重复多次...
                  NVO将堆栈的第一项输出为数字 
                        一个空格。

1

Perl 6,25个字节

这是我能想到的最短的lambda。

{|.[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

Minkolang 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(blah)。或者,如果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

Prolog,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>在线尝试


1

Japt,3个字节

ñÏu

试试吧

ñÏu     :Implicit input of array
ñ       :Sort by
 Ï      :Passing the 0-based index of each through a function
  u     :  Modulo 2 of index

ó c

试试吧

ó c     :Implicit input of array
ó       :Split into 2 arrays of every 2nd item
  c     :Flatten
        :Implicit output

0

Clojure / ClojureScript,52个字节

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

用ClojureScript REPL编写的,也应该是有效的Clojure。



0

Hassium,191字节

这是一个很长的:(
它从args读取数组,所以用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("  ", "")+"]");}

运行并查看与测试用例扩展这里

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.