Drawing a tree from an array












24












$begingroup$


Given a possibly nested, non-empty array of single-digit positive integers (not guaranteed unique), output the ASCII-art representation as a tree, using the box-drawing characters ┌ ┴ ┐ ─ │ ┬ ┼. (These were copied from Code Page 437, but you can use any equivalent representation).



Every integer of the array should be a leaf of the tree. Elements the same level deep in the array should be present at the same level of the tree. All elements should be separated by enough whitespace to be distinct (up to you to determine how wide, minimum of one space between).



For example, given array [[1, [2]], [3, [4, 5]]], output the following tree



 ┌─┴─┐
┌┴┐ ┌┴─┐
1 │ 3 ┌┴┐
2 4 5


For array [1, 2, 3] the tree could look like



┌─┼─┐
1 2 3


But the array [[1, 2, 3]] would look like




┌─┼─┐
1 2 3


While the array [1, [1, [1, [1]]]] could look like



 ┌─┴┐
1 ┌┴─┐
1 ┌┴┐
1 │
1


As a more complicated example, [1, [[[2, 3], 4], 5]] could be



┌┴───┐
1 ┌─┴┐
┌─┴┐ 5
┌┴┐ 4
2 3


or several other variations.






  • Input and output can be given by any convenient method.

  • You can print it to STDOUT or return it as a function result.

  • Either a full program or a function are acceptable.

  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately.


  • Standard loopholes are forbidden.

  • This is code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.










share|improve this question











$endgroup$












  • $begingroup$
    [1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
    $endgroup$
    – Poke
    Feb 13 at 20:39










  • $begingroup$
    @Poke Added as an example. There are several possible variations for that test case.
    $endgroup$
    – AdmBorkBork
    Feb 13 at 21:09






  • 2




    $begingroup$
    The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
    $endgroup$
    – Draco18s
    Feb 13 at 21:34








  • 4




    $begingroup$
    That looks like [1, [[[2, 3]], [4], 5]] to me.
    $endgroup$
    – Neil
    Feb 13 at 21:45










  • $begingroup$
    Which (if any) of these alternative input formats would be acceptable?
    $endgroup$
    – Οurous
    Feb 13 at 22:02
















24












$begingroup$


Given a possibly nested, non-empty array of single-digit positive integers (not guaranteed unique), output the ASCII-art representation as a tree, using the box-drawing characters ┌ ┴ ┐ ─ │ ┬ ┼. (These were copied from Code Page 437, but you can use any equivalent representation).



Every integer of the array should be a leaf of the tree. Elements the same level deep in the array should be present at the same level of the tree. All elements should be separated by enough whitespace to be distinct (up to you to determine how wide, minimum of one space between).



For example, given array [[1, [2]], [3, [4, 5]]], output the following tree



 ┌─┴─┐
┌┴┐ ┌┴─┐
1 │ 3 ┌┴┐
2 4 5


For array [1, 2, 3] the tree could look like



┌─┼─┐
1 2 3


But the array [[1, 2, 3]] would look like




┌─┼─┐
1 2 3


While the array [1, [1, [1, [1]]]] could look like



 ┌─┴┐
1 ┌┴─┐
1 ┌┴┐
1 │
1


As a more complicated example, [1, [[[2, 3], 4], 5]] could be



┌┴───┐
1 ┌─┴┐
┌─┴┐ 5
┌┴┐ 4
2 3


or several other variations.






  • Input and output can be given by any convenient method.

  • You can print it to STDOUT or return it as a function result.

  • Either a full program or a function are acceptable.

  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately.


  • Standard loopholes are forbidden.

  • This is code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.










share|improve this question











$endgroup$












  • $begingroup$
    [1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
    $endgroup$
    – Poke
    Feb 13 at 20:39










  • $begingroup$
    @Poke Added as an example. There are several possible variations for that test case.
    $endgroup$
    – AdmBorkBork
    Feb 13 at 21:09






  • 2




    $begingroup$
    The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
    $endgroup$
    – Draco18s
    Feb 13 at 21:34








  • 4




    $begingroup$
    That looks like [1, [[[2, 3]], [4], 5]] to me.
    $endgroup$
    – Neil
    Feb 13 at 21:45










  • $begingroup$
    Which (if any) of these alternative input formats would be acceptable?
    $endgroup$
    – Οurous
    Feb 13 at 22:02














24












24








24


2



$begingroup$


Given a possibly nested, non-empty array of single-digit positive integers (not guaranteed unique), output the ASCII-art representation as a tree, using the box-drawing characters ┌ ┴ ┐ ─ │ ┬ ┼. (These were copied from Code Page 437, but you can use any equivalent representation).



Every integer of the array should be a leaf of the tree. Elements the same level deep in the array should be present at the same level of the tree. All elements should be separated by enough whitespace to be distinct (up to you to determine how wide, minimum of one space between).



For example, given array [[1, [2]], [3, [4, 5]]], output the following tree



 ┌─┴─┐
┌┴┐ ┌┴─┐
1 │ 3 ┌┴┐
2 4 5


For array [1, 2, 3] the tree could look like



┌─┼─┐
1 2 3


But the array [[1, 2, 3]] would look like




┌─┼─┐
1 2 3


While the array [1, [1, [1, [1]]]] could look like



 ┌─┴┐
1 ┌┴─┐
1 ┌┴┐
1 │
1


As a more complicated example, [1, [[[2, 3], 4], 5]] could be



┌┴───┐
1 ┌─┴┐
┌─┴┐ 5
┌┴┐ 4
2 3


or several other variations.






  • Input and output can be given by any convenient method.

  • You can print it to STDOUT or return it as a function result.

  • Either a full program or a function are acceptable.

  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately.


  • Standard loopholes are forbidden.

  • This is code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.










share|improve this question











$endgroup$




Given a possibly nested, non-empty array of single-digit positive integers (not guaranteed unique), output the ASCII-art representation as a tree, using the box-drawing characters ┌ ┴ ┐ ─ │ ┬ ┼. (These were copied from Code Page 437, but you can use any equivalent representation).



Every integer of the array should be a leaf of the tree. Elements the same level deep in the array should be present at the same level of the tree. All elements should be separated by enough whitespace to be distinct (up to you to determine how wide, minimum of one space between).



For example, given array [[1, [2]], [3, [4, 5]]], output the following tree



 ┌─┴─┐
┌┴┐ ┌┴─┐
1 │ 3 ┌┴┐
2 4 5


For array [1, 2, 3] the tree could look like



┌─┼─┐
1 2 3


But the array [[1, 2, 3]] would look like




┌─┼─┐
1 2 3


While the array [1, [1, [1, [1]]]] could look like



 ┌─┴┐
1 ┌┴─┐
1 ┌┴┐
1 │
1


As a more complicated example, [1, [[[2, 3], 4], 5]] could be



┌┴───┐
1 ┌─┴┐
┌─┴┐ 5
┌┴┐ 4
2 3


or several other variations.






  • Input and output can be given by any convenient method.

  • You can print it to STDOUT or return it as a function result.

  • Either a full program or a function are acceptable.

  • Any amount of extraneous whitespace is acceptable, so long as the characters line up appropriately.


  • Standard loopholes are forbidden.

  • This is code-golf so all usual golfing rules apply, and the shortest code (in bytes) wins.







code-golf ascii-art data-structures






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 14 at 13:36







AdmBorkBork

















asked Feb 13 at 18:39









AdmBorkBorkAdmBorkBork

28k468241




28k468241












  • $begingroup$
    [1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
    $endgroup$
    – Poke
    Feb 13 at 20:39










  • $begingroup$
    @Poke Added as an example. There are several possible variations for that test case.
    $endgroup$
    – AdmBorkBork
    Feb 13 at 21:09






  • 2




    $begingroup$
    The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
    $endgroup$
    – Draco18s
    Feb 13 at 21:34








  • 4




    $begingroup$
    That looks like [1, [[[2, 3]], [4], 5]] to me.
    $endgroup$
    – Neil
    Feb 13 at 21:45










  • $begingroup$
    Which (if any) of these alternative input formats would be acceptable?
    $endgroup$
    – Οurous
    Feb 13 at 22:02


















  • $begingroup$
    [1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
    $endgroup$
    – Poke
    Feb 13 at 20:39










  • $begingroup$
    @Poke Added as an example. There are several possible variations for that test case.
    $endgroup$
    – AdmBorkBork
    Feb 13 at 21:09






  • 2




    $begingroup$
    The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
    $endgroup$
    – Draco18s
    Feb 13 at 21:34








  • 4




    $begingroup$
    That looks like [1, [[[2, 3]], [4], 5]] to me.
    $endgroup$
    – Neil
    Feb 13 at 21:45










  • $begingroup$
    Which (if any) of these alternative input formats would be acceptable?
    $endgroup$
    – Οurous
    Feb 13 at 22:02
















$begingroup$
[1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
$endgroup$
– Poke
Feb 13 at 20:39




$begingroup$
[1,[[[2,3],4],5]] could be an interesting test case since it needs to have the root artificially extend so the right subtree doesn't collide with the left subtree.
$endgroup$
– Poke
Feb 13 at 20:39












$begingroup$
@Poke Added as an example. There are several possible variations for that test case.
$endgroup$
– AdmBorkBork
Feb 13 at 21:09




$begingroup$
@Poke Added as an example. There are several possible variations for that test case.
$endgroup$
– AdmBorkBork
Feb 13 at 21:09




2




2




$begingroup$
The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
$endgroup$
– Draco18s
Feb 13 at 21:34






$begingroup$
The first example for that test case can't be right. That suggests that the s second element next to the 1 is an array of 3 items: [2,3],4, and 5. But 4 and 5 are not adjacent.
$endgroup$
– Draco18s
Feb 13 at 21:34






4




4




$begingroup$
That looks like [1, [[[2, 3]], [4], 5]] to me.
$endgroup$
– Neil
Feb 13 at 21:45




$begingroup$
That looks like [1, [[[2, 3]], [4], 5]] to me.
$endgroup$
– Neil
Feb 13 at 21:45












$begingroup$
Which (if any) of these alternative input formats would be acceptable?
$endgroup$
– Οurous
Feb 13 at 22:02




$begingroup$
Which (if any) of these alternative input formats would be acceptable?
$endgroup$
– Οurous
Feb 13 at 22:02










3 Answers
3






active

oldest

votes


















12












$begingroup$


Python 3, 400 393 390 bytes





L=len
S,*K=' ┴┼│123456789'
def T(x):
try:return[str(x+0)]
except:
z=[*map(T,x)];q=max(map(L,z))
for p in z:p+=[S*L(p[0])]*(q-L(p))
b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
if e<2:return['│'.center(l),*b]
for i in range(l):
if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
elif 0<s<e:r[i]='─'
c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]


Returns a list of strings from top to bottom.



EDIT 1: Trimmed 7 bytes by avoiding duplication of ┴┼ (net save of 2 bytes), cutting out 0 from the one string, changing how drawing characters are selected from ┬┌┐ (use < instead of ==), and replacing a L(z) I missed with e



EDIT 2: -2 bytes thanks to ovs and -1 byte thanks to Kevin Cruijssen



Try it online!



Ungolfed



def layer(item):
if isinstance(item, int):
return [str(item)]
else:
subs = [layer(sub) for sub in item]
longest = max(map(len, subs))
for sub in subs:
sub += [' ' * len(sub[0])] * (longest - len(sub))
below = [' '.join(l) for l in zip(*subs)]
top = below[0]
l = len(top)
if len(subs) == 1:
return ['│'.center(l), *below]
seen = 0
expected = len(subs)
builder = [' '] * l
for i in range(l):
c = top[i]
if c in '┴┼│123456789':
seen += 1
if seen == 1:
builder[i] = '┌'
elif seen == expected:
builder[i] = '┐'
else:
builder[i] = '┬'
elif 0 < seen < expected:
builder[i] = '─'
center = l // 2
if builder[center] == '┬':
builder[center] = '┼'
else:
builder[center] = '┴'
return [''.join(builder), *below]


Builds a tree from the leaves up, one layer at a time.






share|improve this answer











$endgroup$









  • 2




    $begingroup$
    I added the test-cases to your TIO link Try it online!
    $endgroup$
    – pizzapants184
    Feb 14 at 2:52












  • $begingroup$
    Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
    $endgroup$
    – ovs
    Feb 14 at 10:12






  • 1




    $begingroup$
    e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
    $endgroup$
    – Kevin Cruijssen
    Feb 14 at 14:44



















3












$begingroup$


Clean, 544 506 bytes



Escapes are used to avoid invalid UTF-8 on SE/TIO but counted as one byte as they're valid literals



import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='305'='302'|q==j='301'='304'='277'='332'='263'=toChar v+'0')0\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\q<-[0..k!!3]]\p<-[0..k!!1]];@(L l)#p=twice(p=[[v,r+1:[e+sum([2\[v:_]<-i|0<=v]++zipWith(c j=j!!2-c!!3)t(takeWhile([z:_]=v+z< -1)(tl t)))-x!!1\e<-x]]\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];


Try it online!



Takes input in the format L[I 3, L[I 4, I 5], I 2]..



Connects the trees from the bottom up, left to right, then adjusts the distances from right to left.



Prettified, sort-of:



import StdEnv, Data.List;
:: T = I Int | L [T];
$ l
#m = @l
#k = map maxList (transpose m)
= flatlines [
[
last[
' ':
[
if(v < 0)
if(w < [j])
if(q > hd w)
if(q < last w)
if(any ((==) q) w)
(
if(q == j)
'305'
'302'
)(
if(q == j)
'301'
'304'
)
'277'
'332'
'263'
(toChar v + '0')
\ [v, r, j: w] <- m
| r/2 == p && q >= hd w && q <= last w
]
]
\ q <- [0..k!!3]
]
\p<-[0..k!!1]
];
@ (L l)
#p = twice
( p
= [
[
v, r + 1:
map
(
(+)
(
sum [2 \ [v: _] <- i| 0 <= v]
+ sum (
zipWith
(
[_, _, _, c: _] [_, _, j: _] = j - c
)
t
(
takeWhile ([v: _] = v < 0) (tl t)
)
) * (1 - sign (v + 1))
- x!!1
)
)
x
]
\ i <- inits p
& t <- tails p
& [v, r: x] <- p
]
)
(concatMap @ l)
#g = [g \ [_, 2, g: _] <- p]
=[[-1, 0, (hd g + last g)/2: g]: p];
@ (I i) = [[i, 0, 0, 0]];





share|improve this answer











$endgroup$





















    3












    $begingroup$


    Charcoal, 127 123 bytes



    ↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│


    Try it online! Link is to verbose version of code. Explanation:






    Change the default drawing direction to up since we don't draw anything to the right.



    ≔⟦⟦θ⟧⟧η


    The first step is to convert the nested array representation into an index representation which is a list of all the entries together with the indices of the subarrays, e.g. for the input q=[1, [[[2, 3]], [4], 5]] the 5 is q[1][2] and therefore the list we want is 1, 2. We start with a single entry to process which is a list containing a list of the current indices (i.e. none so far) and the original input.



    Fη«


    Loop over the arrays as we process them. (Conveniently Charcoal will continue to iterate over a list if you push to it during iteration.)



    ≔⊟ιζ


    Get the next array to process.



    ¿⁼Iζ⪫⟦ζ⟧ω


    Is this actually a scalar rather than an array?



    ⊞υ⊞Oιζ


    If so, then the list we had actually belongs on the final list of lists of indices.



    FLζ


    Otherwise, loop over each element in this array...



    ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»


    ... and save it with its new index list so far for further processing. The maximum index of the array is also saved which is used to special-case the last element of the array.



    Wυ«


    We are now ready to loop over the list of index lists. However, the list is not in lexicographical order, so we can't iterate it directly.



    ≔⌊υι


    Find the next element in lexicographical order.



    ≔Φυ¬⁼κιυ


    Remove it from the list.



    J±⊗Lυ⊘⊖Lι


    Jump to the position of the scalar in the output. We can calculate this given that we can keep count of the number of scalars we output and we also know the number of entries in its index list.



    I⊟ι


    Actually print the scalar.



    Wι«


    Loop over the entries in the index list. Again, this isn't simple iteration, because the entries come in pairs, and we also need to be able to break out of the loop.



    ≔⊟ιζ


    Extract the next index from the list.



    ¿ζ«


    If this is not the first element in the list...



    ←§┐┬‹ζ⊟ι


    ... then print or depending on whether this is the last element in the list...



    W⁼KKψ←─


    ... and print enough s to fill up to the previous entry at this level...



    ≔⁰ι»


    ... and clear the variable to break out of the loop since we're done here.



    ¿⊟ι┌¶┴


    Otherwise if this is (the first element of) a multiple-element list then print the ┌┴, leaving the cursor above the to deal with this level's parent.



    ¦│


    Otherwise if this is a 1-element list then just print a and move up a line to deal with this level's parent.






    share|improve this answer











    $endgroup$














      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "200"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f179875%2fdrawing-a-tree-from-an-array%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      12












      $begingroup$


      Python 3, 400 393 390 bytes





      L=len
      S,*K=' ┴┼│123456789'
      def T(x):
      try:return[str(x+0)]
      except:
      z=[*map(T,x)];q=max(map(L,z))
      for p in z:p+=[S*L(p[0])]*(q-L(p))
      b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
      if e<2:return['│'.center(l),*b]
      for i in range(l):
      if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
      elif 0<s<e:r[i]='─'
      c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]


      Returns a list of strings from top to bottom.



      EDIT 1: Trimmed 7 bytes by avoiding duplication of ┴┼ (net save of 2 bytes), cutting out 0 from the one string, changing how drawing characters are selected from ┬┌┐ (use < instead of ==), and replacing a L(z) I missed with e



      EDIT 2: -2 bytes thanks to ovs and -1 byte thanks to Kevin Cruijssen



      Try it online!



      Ungolfed



      def layer(item):
      if isinstance(item, int):
      return [str(item)]
      else:
      subs = [layer(sub) for sub in item]
      longest = max(map(len, subs))
      for sub in subs:
      sub += [' ' * len(sub[0])] * (longest - len(sub))
      below = [' '.join(l) for l in zip(*subs)]
      top = below[0]
      l = len(top)
      if len(subs) == 1:
      return ['│'.center(l), *below]
      seen = 0
      expected = len(subs)
      builder = [' '] * l
      for i in range(l):
      c = top[i]
      if c in '┴┼│123456789':
      seen += 1
      if seen == 1:
      builder[i] = '┌'
      elif seen == expected:
      builder[i] = '┐'
      else:
      builder[i] = '┬'
      elif 0 < seen < expected:
      builder[i] = '─'
      center = l // 2
      if builder[center] == '┬':
      builder[center] = '┼'
      else:
      builder[center] = '┴'
      return [''.join(builder), *below]


      Builds a tree from the leaves up, one layer at a time.






      share|improve this answer











      $endgroup$









      • 2




        $begingroup$
        I added the test-cases to your TIO link Try it online!
        $endgroup$
        – pizzapants184
        Feb 14 at 2:52












      • $begingroup$
        Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
        $endgroup$
        – ovs
        Feb 14 at 10:12






      • 1




        $begingroup$
        e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
        $endgroup$
        – Kevin Cruijssen
        Feb 14 at 14:44
















      12












      $begingroup$


      Python 3, 400 393 390 bytes





      L=len
      S,*K=' ┴┼│123456789'
      def T(x):
      try:return[str(x+0)]
      except:
      z=[*map(T,x)];q=max(map(L,z))
      for p in z:p+=[S*L(p[0])]*(q-L(p))
      b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
      if e<2:return['│'.center(l),*b]
      for i in range(l):
      if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
      elif 0<s<e:r[i]='─'
      c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]


      Returns a list of strings from top to bottom.



      EDIT 1: Trimmed 7 bytes by avoiding duplication of ┴┼ (net save of 2 bytes), cutting out 0 from the one string, changing how drawing characters are selected from ┬┌┐ (use < instead of ==), and replacing a L(z) I missed with e



      EDIT 2: -2 bytes thanks to ovs and -1 byte thanks to Kevin Cruijssen



      Try it online!



      Ungolfed



      def layer(item):
      if isinstance(item, int):
      return [str(item)]
      else:
      subs = [layer(sub) for sub in item]
      longest = max(map(len, subs))
      for sub in subs:
      sub += [' ' * len(sub[0])] * (longest - len(sub))
      below = [' '.join(l) for l in zip(*subs)]
      top = below[0]
      l = len(top)
      if len(subs) == 1:
      return ['│'.center(l), *below]
      seen = 0
      expected = len(subs)
      builder = [' '] * l
      for i in range(l):
      c = top[i]
      if c in '┴┼│123456789':
      seen += 1
      if seen == 1:
      builder[i] = '┌'
      elif seen == expected:
      builder[i] = '┐'
      else:
      builder[i] = '┬'
      elif 0 < seen < expected:
      builder[i] = '─'
      center = l // 2
      if builder[center] == '┬':
      builder[center] = '┼'
      else:
      builder[center] = '┴'
      return [''.join(builder), *below]


      Builds a tree from the leaves up, one layer at a time.






      share|improve this answer











      $endgroup$









      • 2




        $begingroup$
        I added the test-cases to your TIO link Try it online!
        $endgroup$
        – pizzapants184
        Feb 14 at 2:52












      • $begingroup$
        Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
        $endgroup$
        – ovs
        Feb 14 at 10:12






      • 1




        $begingroup$
        e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
        $endgroup$
        – Kevin Cruijssen
        Feb 14 at 14:44














      12












      12








      12





      $begingroup$


      Python 3, 400 393 390 bytes





      L=len
      S,*K=' ┴┼│123456789'
      def T(x):
      try:return[str(x+0)]
      except:
      z=[*map(T,x)];q=max(map(L,z))
      for p in z:p+=[S*L(p[0])]*(q-L(p))
      b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
      if e<2:return['│'.center(l),*b]
      for i in range(l):
      if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
      elif 0<s<e:r[i]='─'
      c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]


      Returns a list of strings from top to bottom.



      EDIT 1: Trimmed 7 bytes by avoiding duplication of ┴┼ (net save of 2 bytes), cutting out 0 from the one string, changing how drawing characters are selected from ┬┌┐ (use < instead of ==), and replacing a L(z) I missed with e



      EDIT 2: -2 bytes thanks to ovs and -1 byte thanks to Kevin Cruijssen



      Try it online!



      Ungolfed



      def layer(item):
      if isinstance(item, int):
      return [str(item)]
      else:
      subs = [layer(sub) for sub in item]
      longest = max(map(len, subs))
      for sub in subs:
      sub += [' ' * len(sub[0])] * (longest - len(sub))
      below = [' '.join(l) for l in zip(*subs)]
      top = below[0]
      l = len(top)
      if len(subs) == 1:
      return ['│'.center(l), *below]
      seen = 0
      expected = len(subs)
      builder = [' '] * l
      for i in range(l):
      c = top[i]
      if c in '┴┼│123456789':
      seen += 1
      if seen == 1:
      builder[i] = '┌'
      elif seen == expected:
      builder[i] = '┐'
      else:
      builder[i] = '┬'
      elif 0 < seen < expected:
      builder[i] = '─'
      center = l // 2
      if builder[center] == '┬':
      builder[center] = '┼'
      else:
      builder[center] = '┴'
      return [''.join(builder), *below]


      Builds a tree from the leaves up, one layer at a time.






      share|improve this answer











      $endgroup$




      Python 3, 400 393 390 bytes





      L=len
      S,*K=' ┴┼│123456789'
      def T(x):
      try:return[str(x+0)]
      except:
      z=[*map(T,x)];q=max(map(L,z))
      for p in z:p+=[S*L(p[0])]*(q-L(p))
      b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
      if e<2:return['│'.center(l),*b]
      for i in range(l):
      if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
      elif 0<s<e:r[i]='─'
      c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]


      Returns a list of strings from top to bottom.



      EDIT 1: Trimmed 7 bytes by avoiding duplication of ┴┼ (net save of 2 bytes), cutting out 0 from the one string, changing how drawing characters are selected from ┬┌┐ (use < instead of ==), and replacing a L(z) I missed with e



      EDIT 2: -2 bytes thanks to ovs and -1 byte thanks to Kevin Cruijssen



      Try it online!



      Ungolfed



      def layer(item):
      if isinstance(item, int):
      return [str(item)]
      else:
      subs = [layer(sub) for sub in item]
      longest = max(map(len, subs))
      for sub in subs:
      sub += [' ' * len(sub[0])] * (longest - len(sub))
      below = [' '.join(l) for l in zip(*subs)]
      top = below[0]
      l = len(top)
      if len(subs) == 1:
      return ['│'.center(l), *below]
      seen = 0
      expected = len(subs)
      builder = [' '] * l
      for i in range(l):
      c = top[i]
      if c in '┴┼│123456789':
      seen += 1
      if seen == 1:
      builder[i] = '┌'
      elif seen == expected:
      builder[i] = '┐'
      else:
      builder[i] = '┬'
      elif 0 < seen < expected:
      builder[i] = '─'
      center = l // 2
      if builder[center] == '┬':
      builder[center] = '┼'
      else:
      builder[center] = '┴'
      return [''.join(builder), *below]


      Builds a tree from the leaves up, one layer at a time.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Feb 14 at 17:30

























      answered Feb 13 at 21:34









      BeefsterBeefster

      2,8001346




      2,8001346








      • 2




        $begingroup$
        I added the test-cases to your TIO link Try it online!
        $endgroup$
        – pizzapants184
        Feb 14 at 2:52












      • $begingroup$
        Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
        $endgroup$
        – ovs
        Feb 14 at 10:12






      • 1




        $begingroup$
        e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
        $endgroup$
        – Kevin Cruijssen
        Feb 14 at 14:44














      • 2




        $begingroup$
        I added the test-cases to your TIO link Try it online!
        $endgroup$
        – pizzapants184
        Feb 14 at 2:52












      • $begingroup$
        Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
        $endgroup$
        – ovs
        Feb 14 at 10:12






      • 1




        $begingroup$
        e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
        $endgroup$
        – Kevin Cruijssen
        Feb 14 at 14:44








      2




      2




      $begingroup$
      I added the test-cases to your TIO link Try it online!
      $endgroup$
      – pizzapants184
      Feb 14 at 2:52






      $begingroup$
      I added the test-cases to your TIO link Try it online!
      $endgroup$
      – pizzapants184
      Feb 14 at 2:52














      $begingroup$
      Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
      $endgroup$
      – ovs
      Feb 14 at 10:12




      $begingroup$
      Nice answer! You can shorten this by two bytes by assigning the space to a variable like this: S,*K=' ┴┼│123456789'.
      $endgroup$
      – ovs
      Feb 14 at 10:12




      1




      1




      $begingroup$
      e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
      $endgroup$
      – Kevin Cruijssen
      Feb 14 at 14:44




      $begingroup$
      e==1 can be e<2 to save a byte (I don't think it ever can be 0, since the challenge states the input is non-empty - and empty inputs would have already failed at the max(map(L,z)) in that case anyway.)
      $endgroup$
      – Kevin Cruijssen
      Feb 14 at 14:44











      3












      $begingroup$


      Clean, 544 506 bytes



      Escapes are used to avoid invalid UTF-8 on SE/TIO but counted as one byte as they're valid literals



      import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='305'='302'|q==j='301'='304'='277'='332'='263'=toChar v+'0')0\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\q<-[0..k!!3]]\p<-[0..k!!1]];@(L l)#p=twice(p=[[v,r+1:[e+sum([2\[v:_]<-i|0<=v]++zipWith(c j=j!!2-c!!3)t(takeWhile([z:_]=v+z< -1)(tl t)))-x!!1\e<-x]]\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];


      Try it online!



      Takes input in the format L[I 3, L[I 4, I 5], I 2]..



      Connects the trees from the bottom up, left to right, then adjusts the distances from right to left.



      Prettified, sort-of:



      import StdEnv, Data.List;
      :: T = I Int | L [T];
      $ l
      #m = @l
      #k = map maxList (transpose m)
      = flatlines [
      [
      last[
      ' ':
      [
      if(v < 0)
      if(w < [j])
      if(q > hd w)
      if(q < last w)
      if(any ((==) q) w)
      (
      if(q == j)
      '305'
      '302'
      )(
      if(q == j)
      '301'
      '304'
      )
      '277'
      '332'
      '263'
      (toChar v + '0')
      \ [v, r, j: w] <- m
      | r/2 == p && q >= hd w && q <= last w
      ]
      ]
      \ q <- [0..k!!3]
      ]
      \p<-[0..k!!1]
      ];
      @ (L l)
      #p = twice
      ( p
      = [
      [
      v, r + 1:
      map
      (
      (+)
      (
      sum [2 \ [v: _] <- i| 0 <= v]
      + sum (
      zipWith
      (
      [_, _, _, c: _] [_, _, j: _] = j - c
      )
      t
      (
      takeWhile ([v: _] = v < 0) (tl t)
      )
      ) * (1 - sign (v + 1))
      - x!!1
      )
      )
      x
      ]
      \ i <- inits p
      & t <- tails p
      & [v, r: x] <- p
      ]
      )
      (concatMap @ l)
      #g = [g \ [_, 2, g: _] <- p]
      =[[-1, 0, (hd g + last g)/2: g]: p];
      @ (I i) = [[i, 0, 0, 0]];





      share|improve this answer











      $endgroup$


















        3












        $begingroup$


        Clean, 544 506 bytes



        Escapes are used to avoid invalid UTF-8 on SE/TIO but counted as one byte as they're valid literals



        import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='305'='302'|q==j='301'='304'='277'='332'='263'=toChar v+'0')0\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\q<-[0..k!!3]]\p<-[0..k!!1]];@(L l)#p=twice(p=[[v,r+1:[e+sum([2\[v:_]<-i|0<=v]++zipWith(c j=j!!2-c!!3)t(takeWhile([z:_]=v+z< -1)(tl t)))-x!!1\e<-x]]\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];


        Try it online!



        Takes input in the format L[I 3, L[I 4, I 5], I 2]..



        Connects the trees from the bottom up, left to right, then adjusts the distances from right to left.



        Prettified, sort-of:



        import StdEnv, Data.List;
        :: T = I Int | L [T];
        $ l
        #m = @l
        #k = map maxList (transpose m)
        = flatlines [
        [
        last[
        ' ':
        [
        if(v < 0)
        if(w < [j])
        if(q > hd w)
        if(q < last w)
        if(any ((==) q) w)
        (
        if(q == j)
        '305'
        '302'
        )(
        if(q == j)
        '301'
        '304'
        )
        '277'
        '332'
        '263'
        (toChar v + '0')
        \ [v, r, j: w] <- m
        | r/2 == p && q >= hd w && q <= last w
        ]
        ]
        \ q <- [0..k!!3]
        ]
        \p<-[0..k!!1]
        ];
        @ (L l)
        #p = twice
        ( p
        = [
        [
        v, r + 1:
        map
        (
        (+)
        (
        sum [2 \ [v: _] <- i| 0 <= v]
        + sum (
        zipWith
        (
        [_, _, _, c: _] [_, _, j: _] = j - c
        )
        t
        (
        takeWhile ([v: _] = v < 0) (tl t)
        )
        ) * (1 - sign (v + 1))
        - x!!1
        )
        )
        x
        ]
        \ i <- inits p
        & t <- tails p
        & [v, r: x] <- p
        ]
        )
        (concatMap @ l)
        #g = [g \ [_, 2, g: _] <- p]
        =[[-1, 0, (hd g + last g)/2: g]: p];
        @ (I i) = [[i, 0, 0, 0]];





        share|improve this answer











        $endgroup$
















          3












          3








          3





          $begingroup$


          Clean, 544 506 bytes



          Escapes are used to avoid invalid UTF-8 on SE/TIO but counted as one byte as they're valid literals



          import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='305'='302'|q==j='301'='304'='277'='332'='263'=toChar v+'0')0\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\q<-[0..k!!3]]\p<-[0..k!!1]];@(L l)#p=twice(p=[[v,r+1:[e+sum([2\[v:_]<-i|0<=v]++zipWith(c j=j!!2-c!!3)t(takeWhile([z:_]=v+z< -1)(tl t)))-x!!1\e<-x]]\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];


          Try it online!



          Takes input in the format L[I 3, L[I 4, I 5], I 2]..



          Connects the trees from the bottom up, left to right, then adjusts the distances from right to left.



          Prettified, sort-of:



          import StdEnv, Data.List;
          :: T = I Int | L [T];
          $ l
          #m = @l
          #k = map maxList (transpose m)
          = flatlines [
          [
          last[
          ' ':
          [
          if(v < 0)
          if(w < [j])
          if(q > hd w)
          if(q < last w)
          if(any ((==) q) w)
          (
          if(q == j)
          '305'
          '302'
          )(
          if(q == j)
          '301'
          '304'
          )
          '277'
          '332'
          '263'
          (toChar v + '0')
          \ [v, r, j: w] <- m
          | r/2 == p && q >= hd w && q <= last w
          ]
          ]
          \ q <- [0..k!!3]
          ]
          \p<-[0..k!!1]
          ];
          @ (L l)
          #p = twice
          ( p
          = [
          [
          v, r + 1:
          map
          (
          (+)
          (
          sum [2 \ [v: _] <- i| 0 <= v]
          + sum (
          zipWith
          (
          [_, _, _, c: _] [_, _, j: _] = j - c
          )
          t
          (
          takeWhile ([v: _] = v < 0) (tl t)
          )
          ) * (1 - sign (v + 1))
          - x!!1
          )
          )
          x
          ]
          \ i <- inits p
          & t <- tails p
          & [v, r: x] <- p
          ]
          )
          (concatMap @ l)
          #g = [g \ [_, 2, g: _] <- p]
          =[[-1, 0, (hd g + last g)/2: g]: p];
          @ (I i) = [[i, 0, 0, 0]];





          share|improve this answer











          $endgroup$




          Clean, 544 506 bytes



          Escapes are used to avoid invalid UTF-8 on SE/TIO but counted as one byte as they're valid literals



          import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='305'='302'|q==j='301'='304'='277'='332'='263'=toChar v+'0')0\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\q<-[0..k!!3]]\p<-[0..k!!1]];@(L l)#p=twice(p=[[v,r+1:[e+sum([2\[v:_]<-i|0<=v]++zipWith(c j=j!!2-c!!3)t(takeWhile([z:_]=v+z< -1)(tl t)))-x!!1\e<-x]]\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];


          Try it online!



          Takes input in the format L[I 3, L[I 4, I 5], I 2]..



          Connects the trees from the bottom up, left to right, then adjusts the distances from right to left.



          Prettified, sort-of:



          import StdEnv, Data.List;
          :: T = I Int | L [T];
          $ l
          #m = @l
          #k = map maxList (transpose m)
          = flatlines [
          [
          last[
          ' ':
          [
          if(v < 0)
          if(w < [j])
          if(q > hd w)
          if(q < last w)
          if(any ((==) q) w)
          (
          if(q == j)
          '305'
          '302'
          )(
          if(q == j)
          '301'
          '304'
          )
          '277'
          '332'
          '263'
          (toChar v + '0')
          \ [v, r, j: w] <- m
          | r/2 == p && q >= hd w && q <= last w
          ]
          ]
          \ q <- [0..k!!3]
          ]
          \p<-[0..k!!1]
          ];
          @ (L l)
          #p = twice
          ( p
          = [
          [
          v, r + 1:
          map
          (
          (+)
          (
          sum [2 \ [v: _] <- i| 0 <= v]
          + sum (
          zipWith
          (
          [_, _, _, c: _] [_, _, j: _] = j - c
          )
          t
          (
          takeWhile ([v: _] = v < 0) (tl t)
          )
          ) * (1 - sign (v + 1))
          - x!!1
          )
          )
          x
          ]
          \ i <- inits p
          & t <- tails p
          & [v, r: x] <- p
          ]
          )
          (concatMap @ l)
          #g = [g \ [_, 2, g: _] <- p]
          =[[-1, 0, (hd g + last g)/2: g]: p];
          @ (I i) = [[i, 0, 0, 0]];






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Feb 15 at 5:52

























          answered Feb 15 at 5:24









          ΟurousΟurous

          7,41611136




          7,41611136























              3












              $begingroup$


              Charcoal, 127 123 bytes



              ↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│


              Try it online! Link is to verbose version of code. Explanation:






              Change the default drawing direction to up since we don't draw anything to the right.



              ≔⟦⟦θ⟧⟧η


              The first step is to convert the nested array representation into an index representation which is a list of all the entries together with the indices of the subarrays, e.g. for the input q=[1, [[[2, 3]], [4], 5]] the 5 is q[1][2] and therefore the list we want is 1, 2. We start with a single entry to process which is a list containing a list of the current indices (i.e. none so far) and the original input.



              Fη«


              Loop over the arrays as we process them. (Conveniently Charcoal will continue to iterate over a list if you push to it during iteration.)



              ≔⊟ιζ


              Get the next array to process.



              ¿⁼Iζ⪫⟦ζ⟧ω


              Is this actually a scalar rather than an array?



              ⊞υ⊞Oιζ


              If so, then the list we had actually belongs on the final list of lists of indices.



              FLζ


              Otherwise, loop over each element in this array...



              ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»


              ... and save it with its new index list so far for further processing. The maximum index of the array is also saved which is used to special-case the last element of the array.



              Wυ«


              We are now ready to loop over the list of index lists. However, the list is not in lexicographical order, so we can't iterate it directly.



              ≔⌊υι


              Find the next element in lexicographical order.



              ≔Φυ¬⁼κιυ


              Remove it from the list.



              J±⊗Lυ⊘⊖Lι


              Jump to the position of the scalar in the output. We can calculate this given that we can keep count of the number of scalars we output and we also know the number of entries in its index list.



              I⊟ι


              Actually print the scalar.



              Wι«


              Loop over the entries in the index list. Again, this isn't simple iteration, because the entries come in pairs, and we also need to be able to break out of the loop.



              ≔⊟ιζ


              Extract the next index from the list.



              ¿ζ«


              If this is not the first element in the list...



              ←§┐┬‹ζ⊟ι


              ... then print or depending on whether this is the last element in the list...



              W⁼KKψ←─


              ... and print enough s to fill up to the previous entry at this level...



              ≔⁰ι»


              ... and clear the variable to break out of the loop since we're done here.



              ¿⊟ι┌¶┴


              Otherwise if this is (the first element of) a multiple-element list then print the ┌┴, leaving the cursor above the to deal with this level's parent.



              ¦│


              Otherwise if this is a 1-element list then just print a and move up a line to deal with this level's parent.






              share|improve this answer











              $endgroup$


















                3












                $begingroup$


                Charcoal, 127 123 bytes



                ↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│


                Try it online! Link is to verbose version of code. Explanation:






                Change the default drawing direction to up since we don't draw anything to the right.



                ≔⟦⟦θ⟧⟧η


                The first step is to convert the nested array representation into an index representation which is a list of all the entries together with the indices of the subarrays, e.g. for the input q=[1, [[[2, 3]], [4], 5]] the 5 is q[1][2] and therefore the list we want is 1, 2. We start with a single entry to process which is a list containing a list of the current indices (i.e. none so far) and the original input.



                Fη«


                Loop over the arrays as we process them. (Conveniently Charcoal will continue to iterate over a list if you push to it during iteration.)



                ≔⊟ιζ


                Get the next array to process.



                ¿⁼Iζ⪫⟦ζ⟧ω


                Is this actually a scalar rather than an array?



                ⊞υ⊞Oιζ


                If so, then the list we had actually belongs on the final list of lists of indices.



                FLζ


                Otherwise, loop over each element in this array...



                ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»


                ... and save it with its new index list so far for further processing. The maximum index of the array is also saved which is used to special-case the last element of the array.



                Wυ«


                We are now ready to loop over the list of index lists. However, the list is not in lexicographical order, so we can't iterate it directly.



                ≔⌊υι


                Find the next element in lexicographical order.



                ≔Φυ¬⁼κιυ


                Remove it from the list.



                J±⊗Lυ⊘⊖Lι


                Jump to the position of the scalar in the output. We can calculate this given that we can keep count of the number of scalars we output and we also know the number of entries in its index list.



                I⊟ι


                Actually print the scalar.



                Wι«


                Loop over the entries in the index list. Again, this isn't simple iteration, because the entries come in pairs, and we also need to be able to break out of the loop.



                ≔⊟ιζ


                Extract the next index from the list.



                ¿ζ«


                If this is not the first element in the list...



                ←§┐┬‹ζ⊟ι


                ... then print or depending on whether this is the last element in the list...



                W⁼KKψ←─


                ... and print enough s to fill up to the previous entry at this level...



                ≔⁰ι»


                ... and clear the variable to break out of the loop since we're done here.



                ¿⊟ι┌¶┴


                Otherwise if this is (the first element of) a multiple-element list then print the ┌┴, leaving the cursor above the to deal with this level's parent.



                ¦│


                Otherwise if this is a 1-element list then just print a and move up a line to deal with this level's parent.






                share|improve this answer











                $endgroup$
















                  3












                  3








                  3





                  $begingroup$


                  Charcoal, 127 123 bytes



                  ↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│


                  Try it online! Link is to verbose version of code. Explanation:






                  Change the default drawing direction to up since we don't draw anything to the right.



                  ≔⟦⟦θ⟧⟧η


                  The first step is to convert the nested array representation into an index representation which is a list of all the entries together with the indices of the subarrays, e.g. for the input q=[1, [[[2, 3]], [4], 5]] the 5 is q[1][2] and therefore the list we want is 1, 2. We start with a single entry to process which is a list containing a list of the current indices (i.e. none so far) and the original input.



                  Fη«


                  Loop over the arrays as we process them. (Conveniently Charcoal will continue to iterate over a list if you push to it during iteration.)



                  ≔⊟ιζ


                  Get the next array to process.



                  ¿⁼Iζ⪫⟦ζ⟧ω


                  Is this actually a scalar rather than an array?



                  ⊞υ⊞Oιζ


                  If so, then the list we had actually belongs on the final list of lists of indices.



                  FLζ


                  Otherwise, loop over each element in this array...



                  ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»


                  ... and save it with its new index list so far for further processing. The maximum index of the array is also saved which is used to special-case the last element of the array.



                  Wυ«


                  We are now ready to loop over the list of index lists. However, the list is not in lexicographical order, so we can't iterate it directly.



                  ≔⌊υι


                  Find the next element in lexicographical order.



                  ≔Φυ¬⁼κιυ


                  Remove it from the list.



                  J±⊗Lυ⊘⊖Lι


                  Jump to the position of the scalar in the output. We can calculate this given that we can keep count of the number of scalars we output and we also know the number of entries in its index list.



                  I⊟ι


                  Actually print the scalar.



                  Wι«


                  Loop over the entries in the index list. Again, this isn't simple iteration, because the entries come in pairs, and we also need to be able to break out of the loop.



                  ≔⊟ιζ


                  Extract the next index from the list.



                  ¿ζ«


                  If this is not the first element in the list...



                  ←§┐┬‹ζ⊟ι


                  ... then print or depending on whether this is the last element in the list...



                  W⁼KKψ←─


                  ... and print enough s to fill up to the previous entry at this level...



                  ≔⁰ι»


                  ... and clear the variable to break out of the loop since we're done here.



                  ¿⊟ι┌¶┴


                  Otherwise if this is (the first element of) a multiple-element list then print the ┌┴, leaving the cursor above the to deal with this level's parent.



                  ¦│


                  Otherwise if this is a 1-element list then just print a and move up a line to deal with this level's parent.






                  share|improve this answer











                  $endgroup$




                  Charcoal, 127 123 bytes



                  ↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│


                  Try it online! Link is to verbose version of code. Explanation:






                  Change the default drawing direction to up since we don't draw anything to the right.



                  ≔⟦⟦θ⟧⟧η


                  The first step is to convert the nested array representation into an index representation which is a list of all the entries together with the indices of the subarrays, e.g. for the input q=[1, [[[2, 3]], [4], 5]] the 5 is q[1][2] and therefore the list we want is 1, 2. We start with a single entry to process which is a list containing a list of the current indices (i.e. none so far) and the original input.



                  Fη«


                  Loop over the arrays as we process them. (Conveniently Charcoal will continue to iterate over a list if you push to it during iteration.)



                  ≔⊟ιζ


                  Get the next array to process.



                  ¿⁼Iζ⪫⟦ζ⟧ω


                  Is this actually a scalar rather than an array?



                  ⊞υ⊞Oιζ


                  If so, then the list we had actually belongs on the final list of lists of indices.



                  FLζ


                  Otherwise, loop over each element in this array...



                  ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»


                  ... and save it with its new index list so far for further processing. The maximum index of the array is also saved which is used to special-case the last element of the array.



                  Wυ«


                  We are now ready to loop over the list of index lists. However, the list is not in lexicographical order, so we can't iterate it directly.



                  ≔⌊υι


                  Find the next element in lexicographical order.



                  ≔Φυ¬⁼κιυ


                  Remove it from the list.



                  J±⊗Lυ⊘⊖Lι


                  Jump to the position of the scalar in the output. We can calculate this given that we can keep count of the number of scalars we output and we also know the number of entries in its index list.



                  I⊟ι


                  Actually print the scalar.



                  Wι«


                  Loop over the entries in the index list. Again, this isn't simple iteration, because the entries come in pairs, and we also need to be able to break out of the loop.



                  ≔⊟ιζ


                  Extract the next index from the list.



                  ¿ζ«


                  If this is not the first element in the list...



                  ←§┐┬‹ζ⊟ι


                  ... then print or depending on whether this is the last element in the list...



                  W⁼KKψ←─


                  ... and print enough s to fill up to the previous entry at this level...



                  ≔⁰ι»


                  ... and clear the variable to break out of the loop since we're done here.



                  ¿⊟ι┌¶┴


                  Otherwise if this is (the first element of) a multiple-element list then print the ┌┴, leaving the cursor above the to deal with this level's parent.



                  ¦│


                  Otherwise if this is a 1-element list then just print a and move up a line to deal with this level's parent.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 28 at 9:19

























                  answered Feb 24 at 22:19









                  NeilNeil

                  83k745179




                  83k745179






























                      draft saved

                      draft discarded




















































                      If this is an answer to a challenge…




                      • …Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.


                      • …Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
                        Explanations of your answer make it more interesting to read and are very much encouraged.


                      • …Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.



                      More generally…




                      • …Please make sure to answer the question and provide sufficient detail.


                      • …Avoid asking for help, clarification or responding to other answers (use comments instead).





                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f179875%2fdrawing-a-tree-from-an-array%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Human spaceflight

                      Can not write log (Is /dev/pts mounted?) - openpty in Ubuntu-on-Windows?

                      File:DeusFollowingSea.jpg