Convert header levels to numbers

4

1

Introduction

Nodes in tree structures (e.g. headings in a long document, law paragraphs, etc.) are often created by assigning a specific header level (h1, h2, etc.) to each item, but outputted with additional node numbers for each level (1., 1.1., etc.), e.g.:

1. Intro (h1)
1.1. About this (h2)
1.2. Target audience (h2)
2. Actual stuff (h1)
3. More stuff (h1)
3.1. Details (h2)
3.1.1. Special points (h3)
3.2. Specifics (h2)
3.2.1. Minutiae (h3)
3.2.2. Petitesses (h3)
3.3. Specifications (h2)
4. Index (h1)
5. Appendices (h1)

Input

Given (by any means) a list of header levels (the X's in hX above) like:

[1,2,2,1,1,2,3,2,3,3,2,1,1]

Input will always begin with a 1, and Inputn+1 is in the range [1,1+Inputn].

Input will only contain numbers in the range [1,256].

Output

Return (by any means) the list of lists (or matrix - see below) of node numbers (dot-separated above):

[[1],[1,1],[1,2],[2],[3],[3,1],[3,1,1],[3,2],[3,2,1],[3,2,2],[3,3],[4],[5]] 

You may return scalars instead of one-element sub-lists:

[1,[1,1],[1,2],2,3,[3,1],[3,1,1],[3,2],[3,2,1],[3,2,2],[3,3],4,5] 

You may return a matrix (or list of lists) which is padded with zeros so that all rows (sub-lists) have the same length:

[[1,0,0]
 [1,1,0]
 [1,2,0]
 [2,0,0]
 [3,0,0]
 [3,1,0]
 [3,1,1]
 [3,2,0]
 [3,2,1]
 [3,2,2]
 [3,3,0]
 [4,0,0]
 [5,0,0]]

Additional rules

The reverse process of all this is just the length of each sub-list. You must also include a reverse program in the same language. Your score is the total byte count of your two programs. If you return zero-padded results on the first prgram, your reverse code must handle such input.

Please explain your code so we all can learn from it.

This is code golf, because I'll need to read it on a phone screen and type it into a computer. - No, really, this is not meme-ness!

Adám

Posted 2016-05-10T07:13:03.277

Reputation: 37 779

3What would [1,3,1] return? – Leaky Nun – 2016-05-10T07:40:04.833

6Why should people bother to write a reverse program if it will not contribute to the score? – Bassdrop Cumberwubwubwub – 2016-05-10T08:48:18.797

Can I only make it work to, you know, 9? (Like 3.2.9 will work but not 3.2.10) – Leaky Nun – 2016-05-10T08:52:05.547

3Maybe you could add some test cases? – R. Kap – 2016-05-10T09:06:53.370

@KennyLau I updated the rules to state that [1,3,1] is invalid input and that any positive input number below 257 is valid. – Adám – 2016-05-11T06:08:28.880

@BassdropCumberwubwubwub Now it IS counted. – Adám – 2016-05-11T06:10:37.130

@R.Kap What is lacking in the existing test case? – Adám – 2016-05-11T06:11:45.417

2You should be more up front that the total score is the sum of the original and reversed program. It's easy to miss tucked away in an additional rule. – xnor – 2016-05-11T08:04:26.333

@xnor forgot to say I did that – Adám – 2016-05-14T22:57:44.423

Returning scalars and one-element lists is both allowed, but what about mixing the two? Is [1, [1, 1], [1, 2], [2], [3], ...] an acceptable output for first program if the reverse program can handle it? – Dennis – 2016-05-15T01:54:05.263

@Dennis Allowed if reverse can handle it. In any case, it would be trivial to force all elements into lists/scalarize singletons. – Adám – 2016-05-16T06:41:50.747

Answers

4

CJam (15 + 4 = 19 bytes)

Mq~{1$0+<))+}%`

Online demo

To reverse,

q~:,

Peter Taylor

Posted 2016-05-10T07:13:03.277

Reputation: 41 901

3

JavaScript (ES6), 47 + 21 = 68 bytes

a=>a.map(l=>b=[...b.slice(0,--l),-~b[l]],b=[])

Explanation:

a=>a.map(l=>            Loop over each header level
 b=[                    Make a new sublist using
  ...b.slice(0,--l),    First l-1 elements from the previous sublist
  -~b[l]],              Plus increment the lth element or default to 1
 b=[])                  Start with an empty sublist

The bitwise not operator is used because it will coerce its operand to a signed 32-bit integer, which will be zero if this is a new level. Negating the result conveniently returns one more than the original number, or 1 in the case of a new level. Reverse process:

a=>a.map(b=>b.length)

Neil

Posted 2016-05-10T07:13:03.277

Reputation: 95 035

Could you maybe explain? – Adám – 2016-05-14T22:58:35.443

2@Nᴮᶻ Writing the explanation exposed a bug in the code. The new code is sadly a byte longer. – Neil – 2016-05-14T23:40:19.480

3

Jelly, 10 8 bytes

Forward, 8 6 bytes

ḣ+Ṭ}ð\

Try it online!

Backward, 2 bytes

L€

Try it online!

How it works

Forward

ḣ+Ṭ}ð\  Main link. Argument: A (list of integers)

    ð\  Cumulatively reduce A by the dyadic chain to the left. Arguments: x, y
ḣ       Head; Truncate x to y items.
  Ṭ}    Untruth; yield a list of y-1 zeroes and 1 one.
 +      Compute the vectorized sum of both results.

Backward

L€      Main link. Argument: A (nested list)

L       Length.
 €      Map the previous link over all items in A.

Dennis

Posted 2016-05-10T07:13:03.277

Reputation: 196 637

2

Pyth, 27 22 + 2 = 24 bytes

This is embarrassingly more than 1 less than half of the bytes that javascript used.

JylQjRJ.uhs*N^JY-VtQQ1

Try it online!

Reverse, 2 bytes

lM

Try it online!

Leaky Nun

Posted 2016-05-10T07:13:03.277

Reputation: 45 011

3Even more embarrassingly, it's longer than the CJam solution. – Peter Taylor – 2016-05-11T08:48:35.647

At least the reverse solution is better. (And with the scores combined you're now only just over a third of the bytes of ES6.) – Neil – 2016-05-11T11:35:11.247

2

Pyth, 11 + 2 = 13 bytes

Forward:

m=X_1<+Y0d1

Demonstration

Backward:

lM

I like this one.

How it works:

m=X_1<+Y0d1
               Implicit: Y = []
m              Map over the input, with d being the map variable
      +Y0      Add a 0 on to the end of Y
     <   d     Slice down to the first d elements
  X_1     1    Increment the last one
 =             Assign the result back to Y

The resultant list will contain each value that Y takes on, which is the desired sequence.

Embarrassment cured.

isaacg

Posted 2016-05-10T07:13:03.277

Reputation: 39 268

1

Ruby, 44 + 17 = 61 bytes

Forward:

->x{l=[]
x.map{|e|l=l[0,e-=1]<<(l[e]||0)+1}}

Backward:

->x{x.map &:size}

Value Ink

Posted 2016-05-10T07:13:03.277

Reputation: 10 608