查找列表的“递归大小”


20

启发自查找列表的“展开大小”

RS不包含任何列表的列表的“递归大小”定义为其长度(包含的项目数),将包含任何列表的列表的“递归大小”定义为其长度与这些列表的递归大小之和。

挑战

编写一个程序或函数,以尽可能少的字节输出任何给定列表的递归大小。

输入是一个列表,可以包含数字,字符串(如果您的语言中有字符串)和类似列表。


例如:

RS([]) = 0

RS([[]]) = 1

RS([4, 5, 6]) = 3
RS(["four", "five", "six"]) = 3
RS(["[[[[]]]]", "[][][][][]", "][][[[]]][]["]) = 3

RS([[4, 5, 6]]) = 4
RS([["four", "five", "six"]]) = 4
RS([["[[[[]]]]", "[][][][][]", "][][[[]]][]["]]) = 4

RS([[4], [5], [6]]) = 6
RS([["four"], ["five"], ["six"]]) = 6
RS([["[[[[]]]]"], ["[][][][][]"], ["][][[[]]][]["]]) = 6

RS([[[[[[[[[]]]]]]]]]) = 8

RS([[],[],[],[],[],[],[],[]]) = 8

RS([[],[],[[]],[[[[]]]]]) = 8

RS([0,[-1],[2.3,-4.3],[5,[6]],[7,[8,9,[10,11,[12,13,14]]]]]) = 22

请注意,如果您的语言没有字符串,但是有字符列表,则"strings"上面包含的示例实际上可能是字符列表,并且结果较大。举个例子:

RS([['f','o','u','r'], ['f','i','v','e'], ['s','i','x']]) = 14

这是,因此最短答案以字节为单位;一如既往,没有滑稽的生意。

非列表输入可能会产生任何输出。
I / O 像往常一样灵活



元素是字符串,数字和递归列表吗?
xnor

注意:经过一些讨论后,限制了列表的内容。我已经编辑了问题以反映这一点。感谢@xnor的输入!
乔纳森·艾伦

2
我觉得这将是一个更好的挑战,而无需考虑字符串。它只是在某些语言中添加字节IMO
Conor O'Brien

@ ConorO'Brien,或者,如果他们希望将字符串视为列表,则应该由应答者来决定。不幸的是,我特别询问了社区“我是否应该添加一些极端情况?”和“是否需要澄清定义?” 九天之内在沙盒中都没有任何回应...现在我想这样的问题会重复吗?
乔纳森·艾伦

Answers:


5

果冻,8 字节

߀-ŒḊ?‘S

在线尝试!

怎么运行的

߀-ŒḊ?‘S  Main link. Argument: x

   ŒḊ?    If x has non-zero depth:
߀          Recursively map the main link over its elements.
  -         Else, yield -1.
      ‘   Increment all integers in the result.
       S  Compute the sum of the result.
          If x is an array, incrementing before adding is equivalent to computing
          the sum of the elements and the length.
          If x is an integer/character, incrementing -1 yields 0, as desired.

13

Python,42个字节

f=lambda x:x*0==[]and len(x)+sum(map(f,x))

对于非列表,输出0。对于列表,输出其长度加上其元素的递归输出之和。

清单在Python 2顺序中位于数字上方和字符串下方,要求[]<=x<''。相反,我们检查x*0==[],而结果0为数字或''字符串。


6

JavaScript(ES6),39 37字节

@ edc65节省了2个字节

f=a=>a.map&&a.map(x=>a-=~f(x),a=0)&&a

38个字节:f=a=>a.map?a.reduce((s,x)=>s+f(x),0):0
Sethi

@Sethi不会为任何输入返回0吗?您必须在其中放置一个1
ETHproductions '16

1
37 :f=a=>a.map&&a.map(x=>a-=~f(x),a=0)&&a-=~比少1个字符,+=1+并且将布尔值转换为整数,则会剪切另一个字符。重用a以避免全局变量t
edc65 '16

@ edc65谢谢,太好了!
ETHproductions 2016年

5

Mathematica,20个字节

Length@Level[#,∞]&

匿名函数。将表达式作为输入并返回数字作为输出。的Unicode字符为U + 221E INFINITY \[Infinity]Level[#,∞]给出输入的子表达式的列表,并对Length@它们进行计数。


繁荣!大满贯扣我的答案。但是我学到了新的东西:)
格雷格·马丁

5

Mathematica,14个字节

LeafCount@#-1&

对我先前的答案进行了小修改。正如我在此处解释的那样,LeafCount已经处理了嵌套的原子值,但是它也计算了最外面的列表,我们需要从结果中减去。


4

Perl,34个字节

递归函数!是的,Perl不仅具有正则表达式,还具有功能!

sub f{@_+f(map ref?@$_:(),@_)if@_}

如果要测试它,可以运行以下命令:

perl -pE 'sub f{@_+f(map ref?@$_:(),@_)if@_}$_=f@{+eval}' <<< '[["four"], ["five"], ["six"]]'

3

Mathematica,32个字节

Length@#+Tr[#0/@#~Select~ListQ]&

未命名的递归函数。摘录#0/@#~Select~ListQ在列表的输入的每个元素上再次调用该函数,并对Tr这些值求和。幸运的是,Mathematica可以很好地利用空列表的长度并从空列表中搜索合格元素,因此不需要基本情况​​。


2

Haskell,52个字节

data L a=E a|N[L a]
r(N n)=1+sum(r<$>n)
r _=1
pred.r

用法示例:

*Main> pred.r $ N[E 0,N[E(-1)],N[E 2.3,E(-4.3)],N[E 5,N[E 6]],N[E 7,N[E 8,E 9,N[E 10,E 11,N[E 12,E 13,E 14]]]]] 
22

Haskell不支持混合列表(例如Int和Int列表),因此我使用自定义列表类型L,该类型既可以是某种类型的元素(-> E a),也可以是其他Ls的列表(-> N[L a])。计算RS是一种简单的递归,其中E计数1N一个加一个再加上其元素的递归大小之和。整个和减去1,所以我通过减去pred

旁注:元素的确切类型和值对算法并不重要,因此我们可以删除仅与抽象元素有关的多态性,然后使用data L=E|N[L]


2

因子105字节

递归函数g。

: g ( o -- l ) [ dup [ sequence? ] [ string? not ] bi and [ [ g ] map sum 1 + ] [ drop 1 ] if ] map sum ;

未打高尔夫球(kinda):

: g ( o -- l ) 
[ dup 
  [ sequence? ] 
  [ string? not ] 
  bi and 
  [ [ g ] map sum 1 + ] 
  [ drop 1 ] 
  if 
] map sum ;

您会发现没有调用,length因为它不是使用内置的长度,而是通过drop 1字符串和非序列实现的。


2

Mathematica,18个字节

(c=-1;++c&//@#;c)&

Mathematica的另一种方法。不像使用内置的那样短,LeafCount但是仍然相当简洁。这利用了在表达式的每个节点上调用函数的MapAll运算符//@,并且我们使用该函数来增加counter c。就像在这种LeafCount情况下,它提供了比我们所需更多的值,因为它也对外部列表头进行计数,因此我们从开始计数-1


2

C#(Visual C#交互式编译器),50字节

int f(Array a)=>a.Length+a.OfType<Array>().Sum(f);

在线尝试!

使用与先前提交的Java答案相同的技术,但利用LINQ来减少答案的长度。

说明:

// f is a method that a accepts
// an array of any underlying type
int f(Array a)=>
  // include the length of the
  // current array in the total
  a.Length+
  // filter the current list to elements
  // that are also arrays
  a.OfType<Array>()
    // recursively call f on each child
    // array and add to cumulative total
    .Sum(f);

2

05AB1E(旧版),22 17 字节

"ε¼D¸D˜Êi®.V"©.V¾

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

说明:

该挑战带来了05AB1E中需要克服的多个挑战:

  1. 尽管自从Elixir重写(λ)以来,05AB1E确实具有递归功能,但它仅对整数序列有用。这是我的答案,作为05AB1E递归函数的示例。因此,我必须找到一种进行递归调用的方法,方法是将部分代码放在字符串中,然后将该字符串作为05AB1E代码递归执行。
  2. 也没有 isList05AB1E中命令,因此我不得不使用一些变通办法来进行检查,方法是利用包装到列表中,进行深度展平并检查是否相等。
  3. 第三,对于多维列表中的一个层次,并没有扁平化。展平功能˜是一种深展平,它删除所有图层并使多维列表成为具有所有最里面值的单个列表。(即[[1,2],[[[3]],4]]成为[1,2,3,4])。

我最终将代码放在顶部,以克服上述所有三个问题。它分为三个主要部分。首先,我们有以下内容:

"..."        # Create a string with 05AB1E code
     ©       # Save this string in the register (without popping)
      .V     # Execute the string as 05AB1E code

该字符串包含以下代码:

ε            # Map each value in the given list by:
             # (this uses the input-list implicitly with the initial call)
 ¼           #  Increase the counter_variable by 1
 D           #  Duplicate the map-value
             #   i.e. STACK "A" becomes "A","A"
             #   i.e. STACK [["B","C"]] becomes [["B","C"]],[["B","C"]]
  ¸          #  Wrap it into a list
             #   i.e. "A" → ["A"]
             #   i.e. [["B","C"]] → [[["B","C"]]]
   D         #  Duplicate that again
             #   i.e. STACK "A",["A"] becomes "A",["A"],["A"]
             #   i.e. STACK [["B","C"]],[[["B","C"]]]
             #    becomes [["B","C"]],[[["B","C"]]],[[["B","C"]]]
    ˜        #  Flatten it
             #   i.e. ["A"] → ["A"]
             #   i.e. [[["B","C"]]] → ["B","C"]
     Ê       #  Check if the wrapped and wrapped+flattened lists are NOT equal
             #   i.e. ["A"] and ["A"] → 0 (falsey)
             #   i.e. [[["B","C"]]] and ["B","C"] → 1 (truthy)
      i      #  If they are:
       ®     #   Push the string from the register
        .V   #   Execute it as 05AB1E code
             #   (this is basically our recursive call, mapping the current value
             #    we duplicated initially again)

使用映射而不是foreach循环,因为该映射具有隐式的y,而foreach循环需要显式的y。不过,我们只关心counter_variable

最后,在完成所有图和内部图之后,我们将:

¾           # Push the counter_variable (which is output implicitly as result)


1

C,174个 167 152字节

递归函数f,该函数泄漏内存(152):

#include"object.h"
size_t f(array_t*a){size_t t=0,i=0;for(;i<array_length(a);i++){object_t*o=array_get_copy(a,i,0);t+=o->type==6?f(o->ary):1;}return t;}

f167,使用引用不会泄漏的递归:

#include"object.h"
size_t f(array_t*a){size_t t=0,i=0;for(;i<array_length(a);i++){object_t**o=array_get_ref(a,i,0);t+=*o->type==t_array?f(*o->ary):1;}return t;}

取消高尔夫:

size_t get_recursize (const array_t* const a) {
  pfn();

  object_failnull(a);

  size_t out = 0;

  for (size_t i = 0; i < array_length(a); i++) {

    object_t** o = array_get_ref(a, i, NULL);

    if ( (*o)->type == t_array ) {

      out += get_recursize((*o)->ary);

    } else {
      ++out;
    }
  }
  return out;
}

“但是,”您问,“可以用C回答吗?当然,C中没有托管数组,并且您真的不能拥有异构数组...?”

我回答:“啊哈,因为我一直在为(GNU-ish)C11和ISO C ++ 11开发一个简单的“对象”系统。

此功能的完整演示程序为:

#include "../calc/object/object.h"

size_t get_recursize (const array_t* const a);

define_array_new_fromctype(ssize_t);

int main (void) {

  size_t len = 6;

  static const ssize_t h[6] = { -1, 3, -5, 7, -9, 11 };

  array_t* a = array_new_from_ssize_t_lit(h, len, t_realint);

  size_t rsize = get_recursize(a);

  printf("Recursive size of a: %zu\n", rsize);

  object_t* asobj = object_new(t_array, a);
  array_destruct(a);

  array_t* b = array_new(NULL, -1);

  for (size_t j = 0; j < 10; j++) {
    array_append(b, asobj);
  }

  object_destruct(asobj);

  rsize = get_recursize(b);

  printf("Recursive size of b: %zu\n", rsize);

  asobj = object_new(t_array, b);
  array_destruct(b);

  array_t* c = array_new(NULL, -1);

  for (size_t i = 0; i < 100; i++) {
    array_append(c, asobj);
  }

  object_destruct(asobj);

  rsize = get_recursize(c);

  printf("Recursive size of c: %zu\n", rsize);

  array_destruct(c);

  return EXIT_SUCCESS;
}

size_t get_recursize (const array_t* const a) {
  pfn();

  object_failnull(a);

  size_t out = 0;

  for (size_t i = 0; i < array_length(a); i++) {

    object_t** o = array_get_ref(a, i, NULL);

    if ( (*o)->type == t_array ) {

      out += get_recursize((*o)->ary);

    } else {
      ++out;
    }
  }
  return out;
}

现在,它位于此处,您需要该存储库才能使用它。

您还需要libfnv为平台编译的Fowler-Noll-Vo哈希库。它在该存储库中,您也可以在此处获取它。

那你可以做 cc -DNODEBUG size.c path/to/libfnv.a -o size

实现不一定高效:

$ valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all ./size
==24127== Memcheck, a memory error detector
==24127== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24127== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==24127== Command: ./size
==24127== 
Recursive size of a: 6
Recursive size of b: 60
Recursive size of c: 6000
==24127== 
==24127== HEAP SUMMARY:
==24127==     in use at exit: 0 bytes in 0 blocks
==24127==   total heap usage: 22,900 allocs, 22,900 frees, 615,584 bytes allocated
==24127== 
==24127== All heap blocks were freed -- no leaks are possible
==24127== 
==24127== For counts of detected and suppressed errors, rerun with: -v
==24127== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

但这确实有效!对master的最后一次提交(此程序在其上进行编译)是2天前,这意味着此提交有效。


1

公理118字节

RS(a:Union(List(Any),Any)):INT==(a case List(Any)=>(g:List(Any):=a;leaf? g=>0;r:=#g;for i in g repeat r:=r+RS(i);r);0)

不打高尔夫球

RS(a:Union(List(Any),Any)):INT==
  a case List(Any)=>
          g:List(Any):=a
          leaf? g=>0
          r:=#g
          for i in g repeat r:=r+RS(i)
          r
  0

结果

(25) -> RS([])=0
   (25)  0= 0
                                        Type: Equation NonNegativeInteger
(26) -> RS([[]]) = 1
   (26)  1= 1
                                           Type: Equation PositiveInteger
(27) -> RS([4, 5, 6]) = 3
   (27)  3= 3
                                           Type: Equation PositiveInteger
(28) -> RS(["four", "five", "six"]) = 3
   (28)  3= 3
                                           Type: Equation PositiveInteger
(29) -> RS(["[[[[]]]]", "[][][][][]", "][][[[]]][]["]) = 3
   (29)  3= 3
                                           Type: Equation PositiveInteger
(30) -> RS([[4, 5, 6]]) = 4
   (30)  4= 4
                                           Type: Equation PositiveInteger
(31) -> RS([["four", "five", "six"]]) = 4
   (31)  4= 4
                                           Type: Equation PositiveInteger
(32) -> RS([["[[[[]]]]", "[][][][][]", "][][[[]]][]["]]) = 4
   (32)  4= 4
                                           Type: Equation PositiveInteger
(33) -> RS([[4], [5], [6]]) = 6
   (33)  6= 6
                                           Type: Equation PositiveInteger
(34) -> RS([["four"], ["five"], ["six"]]) = 6
   (34)  6= 6
                                           Type: Equation PositiveInteger
(35) -> RS([["[[[[]]]]"], ["[][][][][]"], ["][][[[]]][]["]]) = 6
   (35)  6= 6
                                           Type: Equation PositiveInteger
(36) -> RS([[[[[[[[[]]]]]]]]]) = 8
   (36)  8= 8
                                           Type: Equation PositiveInteger
(37) -> RS([[],[],[],[],[],[],[],[]]) = 8
   (37)  8= 8
                                           Type: Equation PositiveInteger
(38) -> RS([[],[],[[]],[[[[]]]]]) = 8
   (38)  8= 8
                                           Type: Equation PositiveInteger
(39) -> RS([0,[-1],[2.3,-4.3],[5,[6]],[7,[8,9,[10,11,[12,13,14]]]]]) = 22
   (39)  22= 22
                                           Type: Equation PositiveInteger
(40) -> RS([['f','o','u','r'], ['f','i','v','e'], ['s','i','x']]) = 14
   (40)  14= 14
                                           Type: Equation PositiveInteger

1

APL(NARS),24个字符,48个字节

{⍬≡⍵:0⋄×≡⍵:(≢⍵)++/∇¨⍵⋄0}

这将是“我的”公理答案的乱抛垃圾。在APL中,无效清单为“⍬” Zilde,用“ []”表示,“⊂⍬”是“ [[]]”,“ 1 2 3´是´[1,2,3]´ecc一些测试:

  RS←{⍬≡⍵:0⋄×≡⍵:(≢⍵)++/∇¨⍵⋄0}
  RS ⍬
0
  RS ⊂⍬
1
  RS  4 5 6
3
  RS ("four")("five")("six")
14
  RS ('f' 'o' 'u' 'r') ('f' 'i' 'v' 'e') ('s' 'i' 'x')
14
  RS ("(((())))")("()()()()()")(")()((()))()(")
33
  RS (⊂4 5 6)
4
  RS (⊂("four")("five")("six")) 
15
  RS (⊂("(((())))")("()()()()()")(")()((()))()(") )
34
  RS (,4) (,5) (,6)
6
  RS ⊂¨("four")("five")("six")
17
  RS ⊂¨("(((())))")("()()()()()")(")()((()))()(") 
36
  RS ⊂⊂⊂⊂⊂⊂⊂⊂⍬
8
  RS ⍬⍬⍬⍬⍬⍬⍬⍬
8
  RS ⍬⍬(⊂⍬)(⊂(⊂(⊂⍬)))
8
  RS 0(,¯1)(2.3 ¯4.3)(5 (,6))(7 (8 9 (10 11 (12 13 14))))  
22     

为了打印其他类型的结果,练习建议我们需要一个其他功能(练习中的功能RS和Rs应该都可以)

  Rs←{⍬≡⍵:0⋄(''≡0↑⍵)∨0=≡⍵:0⋄(≢⍵)++/∇¨⍵}
  Rs ("four")("five")("six")
3
  Rs ("(((())))")("()()()()()")(")()((()))()(")
3
  Rs (⊂("four")("five")("six"))
4
  Rs (⊂("(((())))")("()()()()()")(")()((()))()(") )
4
  Rs ⊂¨("four")("five")("six")
6
  Rs ⊂¨("(((())))")("()()()()()")(")()((()))()(")
6
  Rs 0(,¯1)(2.3 ¯4.3)(5 (,6))(7 (8 9 (10 11 (12 13 14))))
22
  Rs ('f' 'o' 'u' 'r') ('f' 'i' 'v' 'e') ('s' 'i' 'x')
3

为了查看某些输入的外观,我们使用o函数:

  o←⎕fmt
  o 0(,¯1)(2.3 ¯4.3)(5 (,6))(7 (8 9 (10 11 (12 13 14))))
┌5─────────────────────────────────────────────────────────┐
│  ┌1──┐ ┌2────────┐ ┌2─────┐ ┌2──────────────────────────┐│
│0 │ ¯1│ │ 2.3 ¯4.3│ │  ┌1─┐│ │  ┌3──────────────────────┐││
│~ └~──┘ └~────────┘ │5 │ 6││ │7 │    ┌3────────────────┐│││
│                    │~ └~─┘2 │~ │8 9 │      ┌3────────┐││││
│                    └∊─────┘ │  │~ ~ │10 11 │ 12 13 14│││││
│                             │  │    │~~ ~~ └~────────┘2│││
│                             │  │    └∊────────────────┘3││
│                             │  └∊──────────────────────┘4│
│                             └∊──────────────────────────┘5
└∊─────────────────────────────────────────────────────────┘

此打印Zilde,以及一个8 Zilde列表:

  o ⍬
┌0─┐
│ 0│
└~─┘
  o ⍬⍬⍬⍬⍬⍬⍬⍬
┌8──────────────────────────────────────┐
│┌0─┐ ┌0─┐ ┌0─┐ ┌0─┐ ┌0─┐ ┌0─┐ ┌0─┐ ┌0─┐│
││ 0│ │ 0│ │ 0│ │ 0│ │ 0│ │ 0│ │ 0│ │ 0││
│└~─┘ └~─┘ └~─┘ └~─┘ └~─┘ └~─┘ └~─┘ └~─┘2
└∊──────────────────────────────────────┘

1

Java,96个字节

int c(Object[]a){int r=a.length;for(var i:a)r+=i instanceof Object[]?c((Object[])i):0;return r;}

在线尝试。

说明:

int c(Object[]a){  // Recursive method with Object-array parameter and integer return-type
  int r=a.length;  //  Result-sum, starting at the size of the input-array
  for(var i:a)     //  Loop over the input-array:
    r+=            //   Increase the result-sum by:
       i instanceof Object[]?
                   //    If the current item is an array:
        c((Object[])i) 
                   //     A recursive call with this item
       :           //    Else:
        0;         //     0 (so leave the result-sum the same)
  return r;}       //  Return the result-sum

1

附件,21字节

{#_+Sum!$=>IsArray\_}

在线尝试!

事实证明,在Attache中C#方法非常短。

备择方案

25字节 f[x]:=#x+Sum!f=>IsArray\x

26个字节 f[x]:=#x+Sum[f=>IsArray\x]

35字节 f:=Sum##{If[IsArray@_,1+f@_,1]}=>Id

35字节 f:=Sum@Map[{If[IsArray@_,1+f@_,1]}]

37字节 f[x]:=Sum[{If[IsArray@_,1+f@_,1]}=>x]


1

Clojure,79 77 51字节

输入必须是列表,而不是向量。都可以使用来支持sequential?

(defn f[i](if(seq? i)(apply +(count i)(map f i))0))

以前:

(defn f[i](if(seq? i)(if(some seq? i)(apply +(count i)(map f i))(count i))0))

-1

Python,72个字节

l=lambda a:0if len(a)==0else len(a)+sum(l(i)for i in a if type(i)==list)

您可以在那里删除一些空间
蓝色

具体而言,在0和之间,以及和之间if0以及之间。else)for
扎卡里

2
如果您的聊天机器人帐户需要代表,请考虑对该网站做出有意义的贡献。相对于预先存在的42字节Python答案,这绝对没有任何增加。
丹尼斯
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.