Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Given a non-flat list of integers, output a list of lists containing the integers in each nesting level, starting with the least-nested level, with the values in their original order in the input list when read left-to-right. If two or more lists are at the same nesting level in the input list, they should be combined into a single list in the output. The output should not contain any empty lists - nesting levels that contain only lists should be skipped entirely.

You may assume that the integers are all in the (inclusive) range [-100, 100]. There is no maximum length or nesting depth for the lists. There will be no empty lists in the input - every nesting level will contain at least one integer or list.

The input and output must be in your language's native list/array/enumerable/iterable/etc. format, or in any reasonable, unambiguous format if your language lacks a sequence type.

Examples

[1, 2, [3, [4, 5], 6, [7, [8], 9]]] => [[1, 2], [3, 6], [4, 5, 7, 9], [8]]

[3, 1, [12, [14, [18], 2], 1], [[4]], 5] => [[3, 1, 5], [12, 1], [14, 2, 4], [18]]

[2, 1, [[5]], 6] => [[2, 1, 6], [5]]

[[54, [43, 76, [[[-19]]]], 20], 12] => [[12], [54, 20], [43, 76], [-19]]

[[[50]], [[50]]] => [[50, 50]]
share|improve this question

11 Answers 11

up vote 4 down vote accepted

Pyth, 17

 us-GeaYsI#GQ)S#Y

The leading space is important. This filters the list on whether the values are invariant on the s function, then removes these values from the list and flatten it one level. The values are also stored in Y and when we print we remove the empty values by filtering if the sorted value of the list is truthy.

Test Suite

Alternatively, a 15 byte answer with a dubious output format:

 us-GpWJsI#GJQ)

Test Suite

Expansion:

 us-GeaYsI#GQ)S#Y     ##   Q = eval(input)
 u          Q)        ##   reduce to fixed point, starting with G = Q
        sI#G          ##   get the values that are not lists from G
                      ##   this works because s<int> = <int> but s<list> = flatter list
      aY              ##   append the list of these values to Y
     e                ##   flatten the list
   -G                 ##   remove the values in the list from G
              S#Y     ##   remove empty lists from Y
share|improve this answer

Mathematica, 56 54 52 bytes

-2 bytes due to Alephalpha.

-2 bytes due to CatsAreFluffy.

Cases[#,_?AtomQ,{i}]~Table~{i,Depth@#}/.{}->Nothing&

Actually deletes empty levels.

share|improve this answer
1  
Cases[#,_?AtomQ,{i}]~Table~{i,Depth@#}~DeleteCases~{}& – alephalpha Feb 20 at 12:14
1  
Cases[#,_?AtomQ,{i}]~Table~{i,Depth@#}/.{}->Nothing&, 2 bytes shorter – CalculatorFeline Feb 20 at 15:31

Python 2, 78 bytes

f=lambda l:l and zip(*[[x]for x in l if[]>x])+f(sum([x for x in l if[]<x],[]))
share|improve this answer

Retina, 79

I know the Retina experts will golf this more, but here's a start:

{([^{}]+)}(,?)([^{}]*)
$3$2<$1>
)`[>}],?[<{]
,
(\d),+[<{]+
$1},{
<+
{
,*[>}]+
}

Try it online.

share|improve this answer

Mathematica 55 64 62 bytes

#~Select~AtomQ/.{}->Nothing&/@Table[Level[#,{k}],{k,Depth@#}]&

%&[{1, 2, {3, {4, 5}, 6, {7, {8}, 9}}}]

{{1, 2}, {3, 6}, {4, 5, 7, 9}, {8}}

share|improve this answer

JavaScript, 112 80 bytes

F=(a,b=[],c=0)=>a.map(d=>d!==+d?F(d,b,c+1):b[c]=[...b[c]||[],d])&&b.filter(d=>d)

Thanks Neil for helping shave off 32 bytes.

share|improve this answer
1  
Lots of opportunities for golfing here. Some easy ones are to remove the !=null as null is falsy anyway. The b= is also unnecessary. Having removed that you can then move the .filter(a=>x) to the &&b which then reduces the outer function to a call to the inner function which you can then inline. I'm left with this: f=(a,b=[],c=0)=>a.map(d=>d[0]?f(d,b,c+1):b[c]=[...b[c]||[],d])&&b.filter(d=>d)‌​. – Neil Feb 19 at 21:59
    
@Neil d[0]? would evaluate false if it was equal to 0, which is within the range [-100,100]. And so would d=>d – Patrick Roberts Feb 19 at 22:23
    
@Neil Threw this one up in a rush, so I knew there were other opportunities to shrink it, but this is much better than I could have done even then. Thanks! Oh, and Patrick is right on the null check being necessary for that reason. I went with d===+d though, since it saves 2 bytes on the null check. – Mwr247 Feb 19 at 22:31
1  
@Dendrobium That won't handle the last case (or any cases with [...,[[...]]]) properly – Mwr247 Feb 19 at 23:18
1  
@PatrickRoberts d=>d is OK since d is always an array or null at that point, but a fair point regarding d[0], although there's always d.map which will be truthy for an array but falsy for a number. – Neil Feb 20 at 0:05

Jelly, 24 bytes

fFW®;©ṛ¹ḟF;/µŒḊ’$¡W®Tị¤;

Try it online!

If newline-separated lists were allowed, this could be golfed down to 14 bytes.

fFṄ¹¹?ḟ@¹;/µ¹¿

Try it online!

share|improve this answer

Python, 108 99 bytes

This seems a bit long to me, but I couldn't make a one-liner shorter, and if I try using or instead of if, I get empty lists in the results.

def f(L):
    o=[];i=[];j=[]
    for x in L:[i,j][[]<x]+=[x]
    if i:o+=[i]
    if j:o+=f(sum(j,[]))
    return o

Try it online

Edit: Saved 9 bytes thanks to Stack Overflow

share|improve this answer
    
You should change your indents to single spaces, so they render properly in the code block. You can also use filter(None,o) to remove empty lists that are on the outermost nesting level of o. – Mego Feb 19 at 21:35
    
I prefer to view my code with tabs. Spaces are evil. – mbomb007 Feb 19 at 21:48
    
SE Markdown converts tabs to 4 spaces, so there's no escaping them anyway :) Using a single space in the Markdown makes the byte count of the code block actually match the byte count of the code. – Mego Feb 19 at 21:50
    
My code itself contains tabs if you look to edit it, though. It's whats on the inside that counts. ;) – mbomb007 Feb 19 at 21:51

MATL, 37 bytes

j']['!=dYsXKu"GK@=)'[\[\],]'32YXUn?1M

Try it online!

Works with current release (13.0.0) of the language/compiler.

This produces the output as lists of comma-separated values, where each list corresponds to the same nesting level (that's MATL's standard way of displaying numeric arrays), and different nesting levels are separated by newlines.

j            % read input as string (row array of chars)
']['!        % 2x1 array containing ']'  and '['
=            % test for equality, all combinations
d            % row array obtained as first row minus second row
Ys           % cumulative sum. Each number is a nesting level
XK           % copy to clibdoard K
u            % unique values: all existing nesting levels
"            % for each nesting level
  G          %   push input
  K          %   push array that indicates nesting level of each input character
  @          %   push level corresponding to this iteration
  =          %   true for characters corresponding to that nesting level
  )          %   pick those characters
  '[\[\],]'  %   characters to be replaced
  32         %   space
  YX         %   regexp replacement
  U          %   only numbers and spaces remain: convert string to array of numbers
  n?         %   if non-empty
    1M       %     push that array of numbers again
             %   end if implicitly
             % end for each implicitly
share|improve this answer

Python 3, 109 bytes

As ever, stupid Python 2 features like comparing ints and lists mean that Python 3 comes out behind. Oh well...

def d(s):
 o=[]
 while s:
  l,*n=[],
  for i in s:
   try:n+=i
   except:l+=[i]
  if l:o+=[l]
  s=n
 return o
share|improve this answer

Perl, 63 bytes

{$o[$x++]=[@t]if@t=grep{!ref}@i;(@i=map{@$_}grep{ref}@i)&&redo}

Input is expected in @i, output produced in @o. (I hope this is acceptable).

Example:

@i=[[54, [43, 76, [[[-19]]]], 20], 12];                              # input

{$o[$x++]=[@t]if@t=grep{!ref}@i;(@i=map{@$_}grep{ref}@i)&&redo}      # the snippet

use Data::Dumper;                                                    # print output
$Data::Dumper::Indent=0;  # keep everything on one line
$Data::Dumper::Terse=1;   # don't print $VAR =
print Dumper(\@o);

Output:

[[12],[54,20],[43,76],[-19]]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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