排序嵌套列表


23

您必须编写对嵌套列表进行排序的程序或函数。以下是对嵌套列表进行排序的规则:

让我们以这个清单为例:

((5, 2), 2, 7, (2, 1, (3, 4)), 9)

此列表中的每个元素都有一个“优先级”。元素计为数字或子列表。首先,在相同深度获得每个元素的优先级。如果元素只是数字,则其优先级与数字本身相同。如果元素是子列表,则其优先级是其中所有数字的总和,不包括任何子子列表。

因此,深度1的所有元素的优先级为:

 (  7 )  2  7  (    3       )  9
((5, 2), 2, 7, (2, 1, (3, 4)), 9)

按优先级对每个元素进行排序。如果有平局,则必须保持与原始列表相同的顺序。

 2  (     3      )  (  7 )  7  9
(2, (2, 1, (3, 4)), (5, 2), 7, 9) 

对每个子列表重复此操作。所以在这个子列表上

(2, 1, (3, 4))

我们的工作重点如下:

 2  1  (  7  )
(2, 1, (3, 4))

如此排序,看起来像:

(1, 2, (3, 4))

(3, 4)已经排序,所以我们完成了。重复(5, 2)产生的结果(2, 5),我们就完成了!我们的最终列表是:

(2, (1, 2, (3, 4)), (2, 5), 7, 9) 

规则:

  • 高度怀疑,但以防万一Mathematica为此提供了某些功能,不允许使用嵌套列表排序内置函数。定期排序功能允许的。

  • I / O可以采用任何合理的格式。

  • 每个子列表将至少包含一个数字或列表。同样,子列表可以嵌套多个级别。例如,中(1, 2, (((3))))(((3)))优先级为0,因为其中只有子列表。

  • 无效的列表(不匹配的括号,非数字,错误的括号类型,负数等)导致未定义的行为。

测试I / O:

(1, 2, 3) ---> (1, 2, 3)

(1, 2, 6, 3, 9, 8) ---> (1, 2, 3, 6, 8, 9)

(4, 3, (2), (1)) ---> ((1), (2), 3, 4)

(4, 3, (2), ((1))) ---> (((1)), (2), 3, 4)

(5, (1, 2, (9, 8))) ---> ((1, 2, (8, 9)), 5)

(3, (1, 2), (2, 1)) ---> (3, (1, 2), (1, 2))

(3, (1, 2, (99)), (2, 1, (34))) ---> (3, (1, 2, (99)), (1, 2, (34)))

(7, 2, (1, (9, 12)), (4, 3, 2, (1, 2))) ---> ((1, (9, 12)), 2, 7, (2, 3, (1, 2), 4))

以字节为单位的最短答案将获胜。


我们可以假设数字是整数吗?
isaacg

@isaacg是的,可以。
DJMcMayhem

Answers:


5

果冻,13个字节

fFSµ€Ụị߀µ¹<?

在线尝试!验证所有测试用例

怎么运行的

fFSµ€Ụị߀µ¹<?  Main link. Input: A (list)

   µ€          Apply the chain to the left to each item B in A.
 F             Flatten B.
f              Filter; intersect B with flattened B, yielding a list.
               This returns the numbers in B if B is a list, [B] if B is a number.
  S            Compute the sum of the resulting list.
     Ụ         Sort the indices of A according to the computed sums.
       ߀      Recursively apply the main link to each B in A.
      ị        Retrieve the items of the list (right) at those indices (left).
         µ     Convert the preceding chain into a single link.
            ?  If:
           <     A compared with itself is truthy:
                   Execute the link to the left.
          ¹      Else, apply the identity function to A.

<数字与自身进行比较()会得出0(虚假),但是将非空列表与自身进行比较会得出一个0列表(真实),因此<可用于将数字与列表区分开。


0为False,但一个0的框为True,但一个空框为False。有趣的Python如何工作。:P

对我来说,看起来像25个字节(使用UTF-8编码时)。
Rotsor

@Rotsor听起来不错。但是,Jelly使用自定义代码页该页将它理解为单个字节的所有256个字符编码。
丹尼斯

17

Python 2中,114个 101 78 73 62字节

k=lambda t:t*(t<[])or t.sort(key=k)or sum(z for z in t if[]>z)

知道有一种更好的方法可以过滤列表。

就地排序python列表(及其子列表)。

https://eval.in/540457 感谢@tac让我知道就地解决方案是可以接受的,感谢@xnor + @feersum进行进一步的优化!


1
更多优化:k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z)
xnor

@xnor我认为解决方案不太正确:eval.in/540447。在此示例中,我们递归到第一个子列表并从中获得第一个子列表z5。然后在条件列表中,对要迭代的列表进行排序(!),因此当我们抓取下一个z时,它也为5。导致总和为10。然后,我们使用这些键对外部列表进行排序,并得到[6,[1,5]],这是不正确的,因为“如果有平局,则必须与原始列表保持相同的顺序。 ” 有趣的是我们sort在两个列表上都调用了两次,所以这只会在相等的键上发生:如果子列表较少,它将进行排序。
Orez

接得好。有趣的是迭代继续到现在排序的列表。我觉得应该仍然有一种较短的方法来保留的None输出t.sort(key=k),但是我没有看到它。
xnor

False出于+扩展目的,为0 sum。但是,无法考虑如何节省字节。
CalculatorFeline

@CatsAreFluffy list.sort返回None,不是False
丹尼斯

4

Lua,172个字节

function p(a)if type(a)~="table"then return a end s(a)local t=0 for i,v in next,a do t=t+p(v)end return t end
function s(t)table.sort(t,function(a,b)return p(a)<p(b)end)end

该函数s根据规则对Lua表(一种数据结构,用作Lua中其他内容的列表)进行排序。


我爱怎么type(a)返回一个字符串

最后用Lua回答。
Leaky Nun

3

Mathematica,50个字节

#0/@SortBy[#,Tr@Cases[#,_Integer,{0,1}]&]~Check~#&

使用的简单递归方法SortBy。忽略消息。


3

Haskell中,160个 151 135字节

import Data.List
data T=N Int|T[T]deriving Show
p(N x)=x
p(T t)=sum$[x|N x<-t]
f(N x)=N x
f(T t)=T$sortBy((.p).compare.p)$map f$t

第一个问题是嵌套列表。Haskell要求列表中的所有元素都具有相同的类型;特别是,整数和整数列表不是同一类型。换句话说,一个可变嵌套列表不是列表,而是玫瑰树!

因此,首先,我们必须为玫瑰树定义数据类型:

data T = N Int | T [T]

(严格的,deriving Show如果你想只需要看到的结果。但是,这是一个技术性问题。)在这个定义的地方,我们可以写一个清单,如(1, 2, (3, 4))

T [N 1, N 2, T [N 3, N 4]]

可读性很差。但是无所谓; 这是一个琐碎的机械翻译。给每个数字加上N每个子树前缀T

现在我们需要计算优先级。如果子树的优先级是它包含的所有元素的总和,那么这将很容易。那将是一个琐碎的递归循环。但由于并非如此,我们需要定义两个函数:一个递归,另一个不递归。

p (N x) = x
p (T t) = sum $ map q t

q (N x) = x
q _     = 0

如果我们将所有子元素相加,那么q不需要存在,从而节省了大量字符。那好吧!

编辑:实际上,一些评论者指出,您可以避免q使用列表理解:[ x | N x <- t]。大家好!

(实际上,p也不需要存在;我们可以让编译器自动生成一个Ord为我们几个字符实例,并且此默认实现将符合规范。)

最后,我们需要对所有子树进行递归并对它们进行排序:

f (N x) = N x
f (T t) = T $ sortBy (\ x y -> compare (p x) (p y)) $ map f $ t

也就是说,f通过将树递归地应用于所有元素(map f),然后调用该sortBy函数对顶级进行排序,从而对树进行排序。第一行说对数字排序没有任何作用,并且是终止递归的必要条件。


2
sortBy (\ x y -> compare (p x) (p y))就是sortOn p。在使用地图中缀版本psum$q<$>t
nimi

@nimi在哪里sortOn定义?我一直想知道...
MathematicalOrchid


2
您仍然可以使用列表解析技巧p(T t)=sum[x|N x<-t]和删除大约16个字节data T=N Int|T[T]deriving Show。:)
内斯(Ness Ness)

1
您是否为计数中的每个换行符添加了2个字节?我认为我们可以将它们视为单身人士。另外,也不需要$in sum$[x|N x<-t]。因此,135-5-1 = 129。:)
威尔·内斯

2

CLISP,380字节

(defun q(L)(if(null L)L(append(append(q(car(s(cdr L)(car L))))(list(car L)))(q(cadr(s(cdr L)(car L))))))))(defun s(L E)(if(not(atom(car L)))(setq L(cons(q(car L))(cdr L))))(cond((null L)'(nil nil))((<(v(car L))E)(list(cons(car L)(car(s(cdr L)E)))(cadr(s(cdr L)E))))(T(list(car(s(cdr L)E))(cons(car L)(cadr(s(cdr L)E)))))))(defun v(L)(if(atom L)L(apply'+(remove-if-not #'atom L))))

用列表调用函数q。

我是一个口齿不清的菜鸟,请不要杀死我^^


哈哈,我希望有人能轻而易举地做到这一点!
DJMcMayhem

1

Pyth,15个字节

L?sIbbossI#NyMb

测试套件

一个递归函数,其工作方式如下:

L?sIbbossI#NyMb
L                  define y(b):
 ?sIb              If b is an integer:          (invariant under the s function)
     b             Return it.
            yMb    Else, apply y recursively to all of the elements of b,
      o            Then sort b by
        sI#N       For each element, the elements of that list that are integers.
                   This is luckily a nop on integers.
       s           Summed.

1

Java,219字节

import java.util.*;List f(List l){l.sort(Comparator.comparing(o->{if(o instanceof Integer)return(Integer)o;f((List)o);return((List) o).stream().filter(i->i instanceof Integer).mapToInt(i->(Integer)i).sum();}));return l;}

带换行符:

import java.util.*;
List f(List l){
    l.sort(Comparator.comparing(o -> {
        if (o instanceof Integer)
            return (Integer) o;
        f((List) o);
        return ((List) o).stream().filter(i -> i instanceof Integer).mapToInt(i -> (Integer) i).sum();
    }));
    return l;
}

有大量的转换工作确实增加了字节数。:P

将整数值馈入比较器,然后在仅将整数值的总和提供给比较器之前,首先对嵌套列表进行排序。这些值是比较器在排序时如何确定其在列表中的位置的方式。

在这里尝试。


1
这是154个字节的相同技术int f(List l){l.sort(Comparator.comparing(o->o instanceof Integer?(int)o:f((List)o)));return l.stream().mapToInt(o->o instanceof Integer?(int)o:0).sum();}
Andreas

我认为还有很多要压缩的东西。
Andreas

但是有两个问题:您不能显式地转换Objectint这样,而挑战似乎要求输出列表。
TNT

通过更改instanceof来检查List而不是Integer,实际上可以节省1个字节。整数是7个字节(不带花括号),但列表是6个字节。
2016年

@TNT可以将对象转换为Java 1.7或更高版本中的基本体。当然,如果Object为null,则会得到一个npe。我认为列表排序没有任何问题,挑战似乎并没有直接解决这个问题。
安德里亚斯

0

JavaScript(ES6),86个字节

f=a=>a.map?a.map(f).sort((a,b)=>p(a)-p(b),p=a=>a.map?a.map(a=>t+=a.map?0:a,t=0)|t:a):a

所有的数组检查:-(


1
map.map.map.map.map.map.map.map.map
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.