13
\$\begingroup\$

Let's define the "unwrapped size" function u of a nested list l (containing only lists) by the following rules:

  • If l is empty, then u(l) is 1.
  • If l is non-empty, u(l) is equal to the sum of the unwrapped sizes of every element in l, plus one.

Your task is to write a program (or function) that takes a list as input and outputs (or returns) the unwrapped size of the list.

Test Cases:

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

This is , so the shortest program (in bytes) wins.

\$\endgroup\$
8
  • 2
    \$\begingroup\$ Can input be taken as a string, i.e. with enclosing quote marks? Can we use () instead of []? \$\endgroup\$
    – Luis Mendo
    Commented Nov 10, 2016 at 15:49
  • \$\begingroup\$ can we take input in this format [[[]][]] instead of this [[[]],[]] in your second example? \$\endgroup\$ Commented Nov 10, 2016 at 16:50
  • \$\begingroup\$ What is the size of ["This is some text [with square brackets in] ...[& maybe more than one pair]"]? \$\endgroup\$ Commented Nov 10, 2016 at 16:54
  • 5
    \$\begingroup\$ Possible duplicate of Find the occurrences of a character in an input string \$\endgroup\$
    – DJMcMayhem
    Commented Nov 11, 2016 at 4:40
  • 2
    \$\begingroup\$ @DrMcMoylex I disagree. While counting the number of ] does seem to be the shortest solution in many languages, there are also a lot of answers that actually solve this challenge via list manipulation, and at least in esolangs counting the occurrences of a fixed character is also quite different from counting the occurrences of an input character. \$\endgroup\$ Commented Nov 11, 2016 at 8:19

33 Answers 33

23
\$\begingroup\$

Retina, 1 byte

]

Try it online! (The first line enables a linefeed-separated test suite.)

By default, Retina counts the number of matches of the given regex in the input. The unwrapped size is simply equal to the number of [] pairs in the input and therefore to the number of ].

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Thre right tool for the job! \$\endgroup\$
    – Cyoce
    Commented Nov 11, 2016 at 8:21
  • \$\begingroup\$ @MartinEnder do you ever add new functions to your language in order to save bytes in a codegolf question? \$\endgroup\$
    – lois6b
    Commented Nov 11, 2016 at 9:45
  • 5
    \$\begingroup\$ @lois6b not retroactively, but I do occasionally improve the language to make it more powerful for future uses. That said, this answer would have worked in the very first version of Retina from back when it was simply a way to run a single regex (/substitution) against the input without syntactic overhead. \$\endgroup\$ Commented Nov 11, 2016 at 10:05
11
\$\begingroup\$

Mathematica, 9 bytes

LeafCount

Turns out there's a built-in for that...

Note that this wouldn't work if the lists actually contained non-list elements. What LeafCount really does is count the number of atomic subexpressions. For input {{}, {{}}}, the expression actually reads:

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

Here the atomic subexpressions are actually the heads List.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Mathematica has a built-in for everything... \$\endgroup\$ Commented Nov 10, 2016 at 22:31
  • 2
    \$\begingroup\$ @Challenger5 Oy, plagiarism. :P \$\endgroup\$ Commented Nov 14, 2016 at 21:43
7
\$\begingroup\$

Brainfuck, 71 61 59 bytes

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

Takes input from STDIN in the format given in the question, and outputs the character whose ASCII code is the list's "unwrapped size."

I'm still a complete amateur at Brainfuck, so there are most likely many optimizations that can still be made.

Try it online!

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)

<.
\$\endgroup\$
5
\$\begingroup\$

JavaScript (ES6), 29 27 bytes

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

i love it when a recursion turns out this cleanly. This is basically a depth-first search of the input, adding 1 whenever the end of an array is reached.

If an empty array were falsy in JS, this could be 24 bytes:

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

But alas, it's not. Other attempts:

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
\$\endgroup\$
5
  • \$\begingroup\$ Would f=a=>a[0]?f(a.pop())+f(a):1 work? (Same byte count though.) \$\endgroup\$
    – Neil
    Commented Nov 10, 2016 at 16:14
  • \$\begingroup\$ @Neil Yes, that's one of the solutions I've already tried. I don't think it's possible to get any shorter... \$\endgroup\$ Commented Nov 10, 2016 at 16:16
  • \$\begingroup\$ (By the way, I would have gone for the extravagant f=a=>a.reduce((n,a)=>n+f(a),1). Now, f=(n,a)=>n+a.reduce(f,1) is only 24 bytes, but sadly the parameters are in the wrong order.) \$\endgroup\$
    – Neil
    Commented Nov 10, 2016 at 16:19
  • \$\begingroup\$ @Neil I actually did that first, except shortening it by 1 byte: f=a=>a.map(a=>n+=f(a),n=1)&&n \$\endgroup\$ Commented Nov 10, 2016 at 16:23
  • \$\begingroup\$ Ah, sorry, I hadn't thought to browse the edit history. \$\endgroup\$
    – Neil
    Commented Nov 10, 2016 at 16:49
4
\$\begingroup\$

Perl, 9 8 7 + 1 = 8 bytes

Requires the -p flag

$_=y;[;

Thanks to @Dada for two byte saves (I'm loving this semicolon exploit btw)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ -p to save 1 byte ;) \$\endgroup\$
    – Dada
    Commented Nov 10, 2016 at 15:05
  • \$\begingroup\$ You can use y;[; to save one more byte \$\endgroup\$
    – Dada
    Commented Nov 10, 2016 at 17:57
4
\$\begingroup\$

CJam, 7 5 bytes

Thanks to Peter Taylor for removing 2 bytes! (e= instead of f=:+)

r'[e=

Try it online!

r         e# Read input
 '[       e# Push open bracket char
   e=     e# Count occurrences. Implicit display
\$\endgroup\$
0
3
\$\begingroup\$

05AB1E, 4 bytes

I'[¢

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

Try it online!

I think it can be golfed more but that 'I' is mandatory, otherwise the input is considered an actual array instead of a string

\$\endgroup\$
3
  • 2
    \$\begingroup\$ "[[[]],[[[[]],[]]],[[[]],[[[[]],[[],[[]]]]]]]" in the input removes that I requirement, though I don't know if that is allowed. \$\endgroup\$ Commented Nov 10, 2016 at 15:49
  • 1
    \$\begingroup\$ @carusocomputing: It's not currently allowed, but that could change (I see Luis asking the OP that same question) \$\endgroup\$
    – Emigna
    Commented Nov 10, 2016 at 15:54
  • \$\begingroup\$ Dang, 14 hours before me. \$\endgroup\$
    – Oliver Ni
    Commented Nov 11, 2016 at 5:30
3
\$\begingroup\$

Ruby, 13 (+1) bytes

p $_.count ?[

Called with -n argument:

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

EDIT: Changed to actually print out the answer

\$\endgroup\$
5
  • \$\begingroup\$ This doesn't seem to print anything. (Unless this is a REPL answer, in which case the language should be specified as Ruby REPL.) \$\endgroup\$ Commented Nov 10, 2016 at 17:20
  • \$\begingroup\$ @Martin Ender♦ The specification allowed for returning the value instead of printing it. \$\endgroup\$
    – Lee W
    Commented Nov 10, 2016 at 19:18
  • \$\begingroup\$ That refers to function submissions. E.g. ->s{s.count ?[} would be a valid submission. \$\endgroup\$ Commented Nov 10, 2016 at 19:31
  • \$\begingroup\$ Is that a general rule? \$\endgroup\$
    – Lee W
    Commented Nov 10, 2016 at 19:44
  • 1
    \$\begingroup\$ See this post for admissible I/O methods. \$\endgroup\$ Commented Nov 10, 2016 at 19:49
3
\$\begingroup\$

Labyrinth, 8 bytes

&-
#,(/!

Try it online!

Explanation

This counts the opening brackets via a bit of bitwise magic. If we consider the results of the character codes of the bitwise AND of [, , and ] with 2, we get:

[ , ]
2 0 0

So if we just sum up the result of this operation for each character, we get twice the value we want.

As for the code itself, the 2x2 block at the beginning is a small loop. On the first iteration &- don't really do anything except that they put an explicit zero on top of the implicit ones at the bottom of the stack. This will be the running total (and it will actually be negative to save a byte later). Then the loop goes as follows:

,   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.

Once we leave the loop, the following linear bit is executed:

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

The IP then hits a dead and turns around. When it tries to executed / again, the program terminates due to the attempted division by zero.

\$\endgroup\$
3
\$\begingroup\$

Python 3 2, 36 23 bytes

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

I noticed that u(l) is equal to the number of [ in the string representation of l, so this program tries to do that. It could probably be golfed further by finding another way to do this, though...

\$\endgroup\$
1
  • 6
    \$\begingroup\$ 23 bytes: lambda x:`x`.count("[") \$\endgroup\$
    – acrolith
    Commented Nov 10, 2016 at 15:20
2
\$\begingroup\$

Python, 26 bytes

f=lambda a:sum(map(f,a))+1

Simple recursive formula.

\$\endgroup\$
2
\$\begingroup\$

C#, 46 41 bytes

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

l is the string of nested list. Test it here.

\$\endgroup\$
6
  • \$\begingroup\$ Use the 4 spaces (before the code) for formatting it into a code block \$\endgroup\$
    – user41805
    Commented Nov 10, 2016 at 19:23
  • \$\begingroup\$ @KritixiLithos oops, I forgot to correctly do that. Thanks for pointing it out :) \$\endgroup\$
    – ave
    Commented Nov 10, 2016 at 19:24
  • \$\begingroup\$ And this has to be a program or a function, this is neither. \$\endgroup\$
    – user41805
    Commented Nov 10, 2016 at 19:27
  • \$\begingroup\$ @KritixiLithos oops, thanks for pointing it out, just fixed it. \$\endgroup\$
    – ave
    Commented Nov 10, 2016 at 19:31
  • 2
    \$\begingroup\$ You can drop the curly braces and return by using an expression bodied function. Also char implicitly casts to int so you can use 91 instead of '[': int u(string l)=>l.Count(c=>c==91); Further, you could drop the function signature and use a lambda method: l=>l.Count(c=>c==91);. \$\endgroup\$
    – milk
    Commented Nov 10, 2016 at 19:55
2
\$\begingroup\$

Jelly, 4 bytes

߀S‘

Doesn't use string manipulation. Try it online! or verify all test cases.

How it works

߀S‘  Main link. Argument: A (array)

߀    Map the main link over A.
  S   Sum. For empty arrays, this yields zero.
   ‘  Increment.
\$\endgroup\$
0
2
\$\begingroup\$

Regex, 1 byte

]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ I'm not sure Regex is a programming language, but even if it is, there's already an identical Retina answer. \$\endgroup\$
    – Dennis
    Commented Nov 12, 2016 at 15:24
2
\$\begingroup\$

Brain-Flak, 63, 61 bytes

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

Try it online! 58 bytes of code, and +3 for the -a flag enabling ASCII input.

Readable version/explanation:

#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
<>
\$\endgroup\$
2
\$\begingroup\$

Befunge, 22 18 16 bytes

~:0#@`#.!#$_3%!+

TryItOnline!

Edit: Thanks to Martin Ender for shaving off 4 bytes!

Edit2: Credit to David Holderness for optimizing out two more

\$\endgroup\$
0
1
\$\begingroup\$

///, 13 bytes

/[/0//]///,//

Output in unary.

Try it online!

Explanation:

/[/0/          Replace every [ with 0
     /]///,//  Remove every ] and ,
\$\endgroup\$
2
  • \$\begingroup\$ How do you pronounce /// ? \$\endgroup\$
    – roblogic
    Commented Dec 16, 2016 at 0:41
  • 1
    \$\begingroup\$ @ropata Slashes \$\endgroup\$
    – acrolith
    Commented Dec 16, 2016 at 12:21
1
\$\begingroup\$

PHP, 35 bytes

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

preg_match_all finds all of the matching instances of the regular expression and returns a number, which is why the short echo tags are needed.

Like most answers, it counts the number of [ in the input and outputs that number

\$\endgroup\$
2
  • 1
    \$\begingroup\$ If you use ] instead of [, you won't have to escape it. \$\endgroup\$ Commented Nov 10, 2016 at 15:36
  • 2
    \$\begingroup\$ count_chars()[91]; does much the same thing but is shorter. \$\endgroup\$
    – user59178
    Commented Nov 10, 2016 at 16:27
1
\$\begingroup\$

Racket 82 bytes

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

Testing:

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

Output:

1
4
19
4
\$\endgroup\$
1
\$\begingroup\$

V, 10 bytes

ÓÛ
ÒC0@"

Try it online!

This contains some unprintable characters, here is the readable version:

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

<C-a> represents "ctrl-a" (ASCII 0x01) and <esc> represents the escape key (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

More fun, less golfy version:

o0kòf]m`jòd

Try it online!

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
\$\endgroup\$
1
\$\begingroup\$

Scala, 15 bytes

s=>s.count(92<)

Ungolfed:

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

count counts how many elements satisfy a predicate, in this case 92<, which is the method < of 92.

\$\endgroup\$
1
\$\begingroup\$

O, 15 bytes

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

Try it here!

In the input, any commas must be either removed or replaced by spaces.

Explanation

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.

If we're allowed to take work on a string: 10 bytes

ie\']-e@-p
\$\endgroup\$
1
\$\begingroup\$

><>, 21 20 18 bytes

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

Edit: score 1 for goto statements!

Edit 2: Apparently ><> differs from Befunge in that it allows non-zero IP offset after wrapping (in other words, by using a trampoline instruction, I can wrap to (1, 0) instead of (0, 0)). Interesting.

TryItOnline!

\$\endgroup\$
0
1
\$\begingroup\$

Brainfuck, 28 bytes

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

Try it online.

This counts the number of input characters divisible by 3, i.e. the number of ] characters.

Alternate 34-byte solution counting [ characters directly and relying on 8-bit cells:

,
[
  <-[>-<---]
  >------
  [>-<[-]]
  >+<,
]
>.
\$\endgroup\$
0
1
\$\begingroup\$

C, 48 46 Bytes

Saved two bytes thanks to 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;}

Test code

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

Test cases

a.exe
1
4
19
\$\endgroup\$
2
  • \$\begingroup\$ Change *v++^91?0:i++ to i+=*v==91 to save 3 bytes. \$\endgroup\$ Commented Nov 10, 2016 at 22:45
  • \$\begingroup\$ @kirbyfan64sos Thanks! I still need to increment v but I can use i+=*v++==91 to save two bytes. \$\endgroup\$
    – cleblanc
    Commented Nov 11, 2016 at 14:13
1
\$\begingroup\$

tinylisp repl, 39 bytes

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

Defines a function u that can be called like (u (q ((())()) )) (for the second test case). Doing it in the repl saves 4 bytes due to auto-closed parentheses.

Explanation

(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

The x-(0-y) construct is necessary because tinylisp doesn't have a built-in addition function, only subtraction.

\$\endgroup\$
1
\$\begingroup\$

Befunge-98, 12 11 10 9 bytes

~3%!+2j@.

TryItOnline!

Edit: Thanks to Martin Ender for shaving off a byte

\$\endgroup\$
0
1
\$\begingroup\$

Haskell, 20 19 17 bytes

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

Try it online!

Takes the list as string and puts a 1 in a list for each ], then sums up all the 1s.


Pointfree version: (19 bytes)

length.filter(>'[')

Assumes , [ ] are the only chars in the string. Filters the list to get all chars greater than [, which are all ] and returns the length.

Usage:

Prelude> length.filter(=='[')$"[[[]],[[[[]],[]]],[[[]],[[[[]],[[],[[]]]]]]]"
19
\$\endgroup\$
0
\$\begingroup\$

Bash + coreutils, 29 bytes

f()(echo $1|tr -d -c [|wc -c)
\$\endgroup\$
1
  • \$\begingroup\$ You can remove most of this and just do tr -d -c [|wc -c, which will by default read the list from standard input. \$\endgroup\$ Commented Nov 10, 2016 at 22:42
0
\$\begingroup\$

DASH, 14 bytes

(ss[len;!> ="]

Simply counts ]'s. Usage:

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

Bonus solution, 15 bytes

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

This one recursively counts from a real list. Usage:

(f\@+1sum ->#f#0)[[]]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.