Знайдіть "Рекурсивний розмір" списку


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

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

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



Чи будуть елементами рядки, числа та рекурсивні списки?
xnor

Примітка. Обмеження вмісту списків після деякого обговорення. Я відредагував питання, щоб це відобразити. Дякуємо @xnor за вклад!
Джонатан Аллан

2
Я вважаю, що це буде кращим завданням, не враховуючи рядків. Це лише додавання байтів до деяких мов IMO
Conor O'Brien

@ ConorO'Brien або, можливо, я мав би зробити це відповіддю, якби вони хотіли розглядати рядок як список чи ні. На жаль, я спеціально запитав у спільноти "Чи є якісь крайові випадки, які я повинен додати?", І "Чи потрібне уточнення визначення?" і я не отримав відповіді у пісочниці протягом дев'яти днів ... і тепер я думаю, що таке питання було б дублікатом?
Джонатан Аллан

Відповіді:


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

Пітон, 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 байт

Збережено 2 байти завдяки @ edc65

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 Чи не поверне це значення 0 для будь-якого введення? Ви повинні 1десь покласти туди.
ETHproductions

1
37: f=a=>a.map&&a.map(x=>a-=~f(x),a=0)&&a. -=~на 1 char менше, +=1+і, перетворивши булеве значення в ціле число, воно скоротить інший символ. Повторне використання , aщоб уникнути глобальної змінноїt
edc65

@ edc65 Дякую, це чудово!
ETHproductions

5

Математика, 20 байт

Length@Level[#,∞]&

Анонімна функція. Приймає вираз як вхідний і повертає число як вихід. Символ Unicode - U + 221E INFINITY for \[Infinity]. Level[#,∞]дає список підсупрезень введення та Length@підраховує їх.


Бум! Слам занурився на мою відповідь. Але я дізнався щось нове :)
Грег Мартін

5

Математика, 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

Математика, 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який є або елементом якогось типу a (-> E a), або зі списком інших Ls (-> N[L a]). Обчислення РС - це проста рекурсія, де Eпідраховується 1і Nодиниця плюс сума рекурсивних розмірів її елементів. Вся сума відключається на 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 ;

Безумовно (рідко):

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

Ви виявите, що немає дзвінків, lengthтому що замість вбудованої довжини він реалізується drop 1на рядках і не послідовностях.


2

Математика, 18 байт

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

Ще один підхід Mathematica. Не такий короткий, як використання вбудованого, LeafCountале все-таки досить стислий. При цьому використовується MapAllоператор, //@який викликає функцію на кожному вузлі виразу, і ми використовуємо цю функцію для збільшення лічильника c. Як і у LeafCountвипадку, це дає на один більше, ніж нам потрібно, оскільки він також враховує голову зовнішнього списку, тому ми починаємо лічильник з -1.


2

C # (Visual C # Interactive Compiler) , 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. Хоча 05AB1E має рекурсивну функцію після перезапису Elixir ( λ), він корисний лише для цілих послідовностей. Ось моя відповідь як приклад рекурсивної функції 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

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

Рекурсивна, fяка не протікає, використовуючи посилання, на 167 :

#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;
}

"Але як, - запитаєте ви, - чи можна відповісти на це в" С "?

"Ага, - відповідаю," бо я працював над простою системою "об'єктів" для (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;
}

Зараз він живе тут, і вам знадобиться це репо, щоб скористатися цим.

Вам також знадобиться хеш-бібліотека Fowler-Noll-Vo libfnv, складена для вашої платформи. Він знаходиться в цьому сховищі, і ви можете також захопити його тут .

Тоді ви можете зробити 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)

Але це працює! Останнє зобов’язання до майстра (яке було складено цією програмою) було 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 список недійсним буде "Зільде", який ви вказуєте з "[]", ", 'є' [[]] ´, ´ 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

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

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

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

ви можете видалити там пробіли
Blue

Зокрема, між 0і if, 0і else, )і for.
Zacharý

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