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


12

Давайте визначимо функцію "нерозгорнутого розміру" uвкладеного списку l(що містить лише списки) за такими правилами:

  • Якщо lпорожній, то u(l)1.
  • Якщо lвін не порожній, u(l)дорівнює сумі нерозгорнутих розмірів кожного елемента l, плюс один.

Ваше завдання - написати програму (або функцію), яка приймає список як вхід і виводить (або повертає) нерозгорнутий розмір списку.

Випробування:

[]                                           ->  1
[[[]],[]]                                    ->  4
[[[]],[[[[]],[]]],[[[]],[[[[]],[[],[[]]]]]]] -> 19
[[[[]]]]                                     ->  4

Це , тому найкоротша програма (у байтах) виграє.


2
Чи можна вводити дані як рядок, тобто з додаючими лапками? Чи можемо ми використовувати ()замість []?
Луїс Мендо

чи можемо ми взяти вхід у такому форматі [[[]][]]замість цього [[[]],[]]у вашому другому прикладі?
Мукул Кумар

Який розмір ["This is some text [with square brackets in] ...[& maybe more than one pair]"]?
Джонатан Аллан


2
@DrMcMoylex Я не згоден. Хоча підрахунок кількості дій ]здається найкоротшим рішенням у багатьох мовах, є також багато відповідей, які насправді вирішують цю проблему за допомогою маніпуляції зі списком, і принаймні в есолангах підрахунок випадків фіксованого символу також сильно відрізняється від підрахунку виникнення вхідного символу.
Мартін Ендер

Відповіді:


23

Сітківка , 1 байт

]

Спробуйте в Інтернеті! (Перший рядок включає тестовий набір, відокремлений виведенням ліній.)

За замовчуванням Retina підраховує кількість збігів даного регулярного виразу у вхідному документі. Розпакований розмір просто дорівнює кількості []пар на вході, а отже, і кількості ].


1
Правильний інструмент для роботи!
Кіос

@MartinEnder Ви коли-небудь додаєте нові функції до своєї мови, щоб зберегти байти у кодовому гольфі?
lois6b

5
@ lois6b не заднім числом, але я інколи вдосконалюю мову, щоб зробити її більш потужною для подальшого використання. Це означає, що ця відповідь спрацювала б у першій версії Retina ззаду, коли це був просто спосіб запустити один регулярний вираз (/ заміну) проти введення без синтаксичних накладних витрат.
Мартін Ендер

11

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

LeafCount

Виявляється, для цього є вбудований ...

Зауважте, що це не буде працювати, якщо списки насправді містили елементи, які не є списками. Що LeafCountнасправді - це підрахунок кількості атомних підвиражень. Для введення {{}, {{}}}вираз насправді читає:

List[List[], List[List[]]]

Тут атомні підвиразки - це фактично голови List .


1
Mathematica має вбудований для всього ...
kirbyfan64sos


7

Brainfuck, 71 61 59 байт

+[>,]<[>-[<->---]+<------[->[-]<]>[-<+>]<[-<[<]<+>>[>]]<]<.

Бере вхід зі STDIN у форматі, заданому у запитанні, і виводить символ, кодом ASCII якого є список "розгорнутого розміру".

Я все ще є повноцінним любителем Brainfuck, тому, швидше за все, є багато оптимізацій, які ще можна зробити.

Спробуйте в Інтернеті!

Безголівки:

read input to tape
>>+[>,]<
current tape: (0 0 1 a b *c)
where abc represents input and * is IP

now we loop over each character (from the end)
this loops assumes we are starting on the (current) last char
and it zeroes the entire string by the time it finishes
[

  subtract 91 from this character
  technically we only subtract 85 here and correct the answer
  with the 6 minus signs below
  >-[<->---]
  current tape: (0 0 1 a b cminus91 *0)

  invert the result and put that in the next cell
  +<------[->[-]<]>
  current tape: (0 0 1 a b 0 *c==91)

  move that result back to the original cell
  [-<+>]<
  current tape: (0 0 1 a b *c==91)

  if the result is true we found a brace
  increment the very first cell if so
  [-<[<]<+>>[>]]<
  current tape: (count 0 1 a *b)

]
current tape: (count *0)

<.

5

JavaScript (ES6), 29 27 байт

f=([x,...a])=>x?f(x)+f(a):1

мені подобається, коли рекурсія виявляється це чисто. Це в основному пошук на глибині першого введення, додавання 1, коли досягається кінець масиву.

Якщо порожній масив був хибним у JS, це може бути 24 байти:

f=a=>a?f(a.pop())+f(a):1

Але на жаль, це не так. Інші спроби:

f=a=>a.reduce((n,x)=>n+f(x),1) // Works, but 3 bytes longer
f=a=>a.map(x=>n+=f(x),n=1)&&n  // Works, but 2 bytes longer
f=a=>(x=a.pop())?f(x)+f(a):1   // Works, but 1 byte longer
f=a=>a[0]?f(a.pop())+f(a):1    // Works, but same byte count
f=a=>a+a?f(a.pop())+f(a):1     // Doesn't work on any array containing 1 sub-array
f=a=>a-1?f(a.pop())+f(a):1     // Same

Було б f=a=>a[0]?f(a.pop())+f(a):1працювати? (Хоча кількість байтів.)
Ніл

@Neil Так, це одне з рішень, які я вже спробував. Я не думаю, що можна отримати коротше ...
ETHproductions

(До речі, я б пішов на екстравагантний f=a=>a.reduce((n,a)=>n+f(a),1). Зараз f=(n,a)=>n+a.reduce(f,1)це всього лише 24 байти, але, на жаль, параметри не в тому порядку.)
Ніл

@Neil Я насправді зробив це першим, окрім скорочення його на 1 байт:f=a=>a.map(a=>n+=f(a),n=1)&&n
ETHproductions

Ах, вибачте, я не думав переглядати історію редагування.
Ніл

4

Perl, 9 8 7 + 1 = 8 байт

Потрібен -pпрапор

$_=y;[;

Дякую @Dada за два байтові збереження (я люблю цю крапку з комою в точку)


1
-pщоб зберегти 1 байт;)
Дада

Можна y;[;зберегти ще один байт
Dada


3

05AB1E , 4 байти

I'[¢

I    Get input as a string
 '[¢ Count the opening square brackets and implicitly print them

Спробуйте в Інтернеті!

Я думаю, що можна більше грати в гольф, але те, що "я" є обов'язковим, інакше введення вважається фактичним масивом замість рядка


2
"[[[]],[[[[]],[]]],[[[]],[[[[]],[[],[[]]]]]]]"у введенні знімається ця Iвимога, хоча я не знаю, чи це дозволено.
Чарівний восьминіг Урна

1
@carusocomputing: Наразі це не дозволено, але це може змінитися (я бачу, Луїс задає ОП те саме питання)
Emigna

Данг, за 14 годин до мене.
Олівер Ні

3

Лабіринт , 8 байт

&-
#,(/!

Спробуйте в Інтернеті!

Пояснення

Це враховує дужки, що відкриваються, за допомогою трохи побітної магії. Якщо розглядати результати символьних кодів побітовое І [, ,і ]з 2, ми одержуємо:

[ , ]
2 0 0

Отже, якщо ми просто підсумовуємо результат цієї операції для кожного символу, ми отримуємо вдвічі більше значення, яке ми хочемо.

Що стосується самого коду, то блок 2x2 на початку - це невеликий цикл. На першій ітерації &-насправді нічого не робиться, окрім того, що вони ставлять явний нуль поверх неявних у нижній частині стека. Це буде загальна кількість (і фактично буде негативно зберегти байт пізніше). Потім цикл виходить наступним чином:

,   Read character. At EOF this gives -1 which causes the instruction pointer to
    leave the loop. Otherwise, the loop continues.
#   Push the stack depth, 2.
&   Bitwise AND.
-   Subtract from running total.

Після виходу з циклу виконується наступний лінійний біт:

(   Decrement to turn the -1 into a -2.
/   Divide negative running total by -2 to get desired result.
!   Print.

Потім IP потрапляє до мертвого і обертається. При спробі /повторного виконання програма припиняється через спробу поділу на нуль.


3

Пітон 3 2, 36 23 байти

lambda x:`x`.count("[")

Я помітив, що u(l)це дорівнює кількості [в рядковому поданні l, тому ця програма намагається це зробити. Можливо, можна було б пограти далі в гольф, знайшовши інший спосіб зробити це, хоча ...


6
23 байти:lambda x:`x`.count("[")
акроліт


2

C #, 46 41 байт

int u(string l){return l.Count(c=>c=='[');}

l - рядок вкладеного списку. Тестуйте це тут .


Використовуйте 4 пробіли (перед кодом) для форматування його в
кодовому

@KritixiLithos на жаль, я забув правильно це зробити. Дякуємо, що вказали на це :)
пр.

І це має бути програма чи функція, це не те.
користувач41805

@KritixiLithos на жаль, дякую, що вказав на це, просто виправив.
пр.

2
Ви можете скинути фігурні фігурні дужки та returnза допомогою функції виразного боді. Також charпобічно ставить на intтак що ви можете використовувати 91замість '[': int u(string l)=>l.Count(c=>c==91);Крім того, ви можете відмовитися від функції підпису і використовувати метод лямбда: l=>l.Count(c=>c==91);.
молоко


2

Ruby, 13 (+1) байт

p $_.count ?[

Викликається -nаргументом:

ruby -ne 'p $_.count ?['

EDIT: Змінено, щоб реально роздрукувати відповідь


Здається, це нічого не друкує. (Якщо це не відповідь на відповідь, в цьому випадку мову слід вказати як Ruby REPL.)
Мартін Ендер

@Martin Ender ♦ Специфікація, що дозволяє повертати значення замість друку.
Лі Ш

Це стосується подання функцій. Наприклад, це ->s{s.count ?[}було б дійсним поданням.
Мартін Ендер

Це загальне правило?
Lee W



2

Мозг-Флак , 63 , 61 байт

{({}[(((()()()){}){}()){({}[()])}{}]){{}(<>{}())(<>)}{}}<>

Спробуйте в Інтернеті! 58 байт коду та +3 для -aпрапора, що дозволяє вводити ASCII.

Читальна версія / пояснення:

#While non-empty:
{

    #subtract
    ({}[

    #91
    (((()()()){}){}()){({}[()])}{}

    ])

    #if non-zero
    {

        # Remove the difference
        {}

        #Increment the counter on the other stack
        (<>{}())

        #Push a zero onto the main stack
        (<>)
    }

    #pop the left-over zero
    {}

#endwhile
}

#Move back to the stack with the counter, implicitly display
<>



1

PHP, 35 байт

<?=preg_match_all('/\[/',$argv[1]);

preg_match_all знаходить усі збігаються екземпляри регулярного виразу і повертає число, саме тому потрібні короткі теги ехо.

Як і більшість відповідей, вона враховує кількість [вхідних даних і виходів цього числа


1
Якщо ви використовуєте ]замість цього [, вам не доведеться уникати цього.
Мартін Ендер

2
count_chars()[91];робить те ж саме, але коротше.
користувач59178

1

Ракетка 82 байти

(define n 0)(let p((l l))(if(null? l)(set! n(+ 1 n))(begin(p(car l))(p(cdr l)))))n

Безголівки:

(define (f l)
  (define n 0)
  (let loop ((l l))
    (if (null? l)
        (set! n (add1 n))
        (begin (loop (first l))
               (loop (rest l)))))
  n)

Тестування:

(f '[]) 
(f '[[[]] []]) 
(f '[[[]] [[[[]] []]] [[[]] [[[[]] [[] [[]]]]]]]) 
(f '[[[[]]]])  

Вихід:

1
4
19
4

1

V , 10 байт

ÓÛ
ÒC0@"

Спробуйте в Інтернеті!

Він містить кілька недрукованих символів, ось читабельна версія:

ÓÛ
Ò<C-a>C0<esc>@"

<C-a>являє собою "ctrl-a" (ASCII 0x01) і <esc>являє собою ключ відходу (ASCII 0x1b).

ÓÛ              " Remove all '['s
                "
Ò<C-a>          " Replace what's left with '<C-a>' (the increment command)
      C         " Delete this line
       0<esc>   " And replace it with a '0'
             @" " Run what we just deleted as V code (A bunch of increment commands

Більш весела, менш гофрована версія:

o0kòf]m`jòd

Спробуйте в Інтернеті!

o0<esc>                     " Put a '0' on the line below us
       k                    " Move back up a line
        ò               ò   " Recursively:
         f]                 "   Move to a right-bracket
           m`               "   Add this location to our jumplist
             j              "   Move down a line
              <C-a>         "   Increment this number
                   <C-o>    "   Move to the previous location
                         d  " Delete the bracket line
                            " Implicitly display

1

Скала, 15 байт

s=>s.count(92<)

Безголівки:

s=>s.count(c=>92<c)

countпідраховує , скільки елементів задовольняють предикат, в цьому випадку 92<, що метод <з 92.


1

О , 15 байт

i~{1\{nJ+}d}J;J

Спробуйте тут!

На вводі будь-які коми повинні бути вилучені або замінені пробілами.

Пояснення

i~{1\{nJ+}d}J;J
i                Read a line of input.
 ~               Evaluate it.
  {        }J;   Define a function and save it into the `J` variable.
                 Currently, the input array is at the top of the stack.
   1\            Push 1 and swap it with the input array.
     {   }d      For each element in the array...
                 Because the array was popped by `d`, 1 is at the TOS.
      nJ+        Recurse and add the result to 1.
              J  Initiate the function call.
                 The result is printed implicitly.

Якщо нам дозволено брати роботу за рядком: 10 байт

ie\']-e@-p

1

> <> , 21 20 18 байт

0i:0(90.;n?|3%0=+!

Редагувати: оцінка 1 для goto заяви!

Редагування 2: Мабуть> <> відрізняється від Befunge тим, що дозволяє ненульовий зсув IP після завершення обгортання (іншими словами, використовуючи інструкцію на батуті, я можу перейти до (1, 0) замість (0, 0)). Цікаво.

СпробуйтеItOnline!


1

Brainfuck, 28 байт

,
[
  -
  [
    -
    [
      >+<-
      [->]
    ]
    >[>>]
    <<<
  ]
  ,
]
>.

Спробуйте в Інтернеті.

При цьому підраховується кількість введених символів, розділених на 3, тобто кількість ]символів.

Чергуйте 34-байтове рішення, що підраховує [символи безпосередньо, і спираючись на 8-бітні комірки:

,
[
  <-[>-<---]
  >------
  [>-<[-]]
  >+<,
]
>.

1

C, 48 46 байт

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

i;f(char*v){for(i=0;*v;i+=*v++==91);return i;}

i;f(char*v){for(i=0;*v;*v++^91?0:i++);return i;}

Код тесту

main()
{
    printf("%d\n", f("[]"));
    printf("%d\n", f("[[[]] []]"));
    printf("%d\n", f("[[[]] [[[[]] []]] [[[]] [[[[]] [[] [[]]]]]]]"));
}

Тестові справи

a.exe
1
4
19

Змініть, *v++^91?0:i++щоб i+=*v==91зберегти 3 байти.
kirbyfan64sos

@ kirbyfan64sos Дякую! Мені ще потрібно збільшити v, але я можу використовувати, i+=*v++==91щоб зберегти два байти.
cleblanc

1

тинілісп репл , 39 байт

(d u(q((L)(i L(s(u(h L))(s 0(u(t L))))1

Визначає функцію, uяку можна назвати подібною(u (q ((())()) )) (для другого тестового випадку). Якщо це зробити в реплиці, то заощаджується 4 байти завдяки автоматично закритим дужкам.

Пояснення

(d u                                      )  Define u as
    (q                                   )    the following, unevaluated
      (                                 )     list (which acts as a function in tinylisp):
       (L)                                   Given arglist of one element, L, return:
          (i L                         )     If L (is nonempty):
              (s(u(h L))             )        Call u on head of L and subtract
                        (s 0        )          0 minus
                            (u(t L))           call u on tail of L
                                      1      Else, 1

x-(0-y)Конструкція є необхідною , оскільки tinylisp не має вбудовані функції складання, тільки віднімання.



1

Haskell, 20 19 17 байт

f s=sum[1|']'<-s]

Спробуйте в Інтернеті!

Приймає список як рядок і додає 1список до кожного ], а потім підсумовує всі 1s.


Версія Pointfree: (19 байт)

length.filter(>'[')

Припущення , [ ]- це єдині символи в рядку. Фільтрує список, щоб отримати всі знаки більше, ніж [усі, ]і повертає довжину.

Використання:

Prelude> length.filter(=='[')$"[[[]],[[[[]],[]]],[[[]],[[[[]],[[],[[]]]]]]]"
19

0

Bash + coreutils, 29 байт

f()(echo $1|tr -d -c [|wc -c)

Ви можете видалити більшу частину цього і просто зробити tr -d -c [|wc -c, що за замовчуванням прочитає список зі стандартного введення.
kirbyfan64sos

0

DASH , 14 байт

(ss[len;!> ="]

Просто рахує ]. Використання:

(ss[len;!> ="]"])"[[]]"

Бонусний розчин, 15 байт

a\@+1sum ->#a#0

Цей рекурсивно зараховується до реального списку. Використання:

(f\@+1sum ->#f#0)[[]]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.