Найдите «развернутый размер» списка


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 Я не согласен. Хотя подсчет числа ]действительно кажется самым коротким решением во многих языках, есть также много ответов, которые фактически решают эту проблему посредством манипулирования списком, и, по крайней мере, в esolangs подсчет вхождений фиксированного символа также весьма отличается от подсчета вхождения входного символа.
Мартин Эндер

Ответы:


23

Сетчатка , 1 байт

]

Попробуйте онлайн! (Первая строка включает набор тестов, разделенных переводом строки.)

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


1
Thre правильный инструмент для работы!
Cyoce

@MartinEnder Вы когда-нибудь добавляли новые функции на свой язык, чтобы сохранить байты в вопросе Codegolf?
lois6b

5
@ lois6b задним числом, но я иногда улучшаю язык, чтобы сделать его более мощным для будущего использования. Тем не менее, этот ответ сработал бы в самой первой версии Retina, когда это был просто способ запустить одно регулярное выражение (/ замена) для ввода без синтаксических издержек.
Мартин Эндер

11

Mathematica, 9 байт

LeafCount

Оказывается, есть встроенный для этого ...

Обратите внимание, что это не сработает, если списки на самом деле содержат не-списочные элементы. Что на LeafCountсамом деле делает, так это подсчитывает количество атомных подвыражений. Для ввода {{}, {{}}}выражение фактически читает:

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

Здесь атомные подвыражения на самом деле являются главами List .


1
Mathematica имеет встроенный для всего ...
kirbyfan64sos


7

Brainfuck, 71 61 59 байт

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

Принимает входные данные из STDIN в формате, указанном в вопросе, и выводит символ, код ASCII которого является «развернутым размером» списка.

Я все еще начинающий любитель в Brainfuck, так что, скорее всего, еще можно сделать много оптимизаций.

Попробуйте онлайн!

Ungolfed:

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

Попробуйте онлайн!

Я думаю, что это может быть больше, но «I» является обязательным, в противном случае ввод считается фактическим массивом, а не строкой


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

Python 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 пробела (перед кодом) для форматирования его в блок кода
user41805

@KritixiLithos К сожалению, я забыл правильно сделать это. Спасибо за указание на это :)
Ave

И это должна быть программа или функция, это ни то, ни другое.
user41805 10.11.16

@KritixiLithos Ой, спасибо за указание на это, только что исправил.
Авен

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


2

Рубин, 13 (+1) байт

p $_.count ?[

Вызывается с -nаргументом:

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

РЕДАКТИРОВАТЬ: Изменено на самом деле распечатать ответ


Кажется, это ничего не печатает. (Если это не ответ REPL, в этом случае язык должен быть указан как Ruby REPL.)
Мартин Эндер

@Martin Ender ♦ В спецификации разрешено возвращать значение вместо его печати.
Ли W

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

Это общее правило?
Ли W



2

Brain-Flak , 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];делает то же самое, но короче.
user59178 10.11.16

1

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

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

Ungolfed:

(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<)

Ungolfed:

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

countподсчитывает , сколько элементов удовлетворяют предикат, в этом случае 92<, что метод <из 92.


1

O , 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)). Интересный.

TryItOnline!


1

Brainfuck, 28 байт

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

Попробуйте онлайн.

Это подсчитывает количество входных символов, делимых на 3, то есть количество ] символов.

Альтернативное 34-байтовое решение, которое подсчитывает [символы напрямую и полагается на 8-битные ячейки:

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

1

С, 48 46 Bytes

Сохранено два байта благодаря 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 ((())()) ))(для второго контрольного примера). Выполнение этого в repl экономит 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.