JavaScript (ES2019), 51 48 47 bytes
i=0;f=(v=[])=>[i+=v.length-!!i,...v.flatMap(f)]
Attempt This Online!
Input requires undefined
as leaves. Output includes initial size and trailing 0
.
I assume the output must be a flat array instead of allowing nested array. If nested array is acceptable then there is this 40-byte solution:
i=0;f=(v=[])=>[i+=v.length-!!i,v.map(f)]
Algorithm
Instead of implementing the specified process and constructing the intermediate arrays, this submission uses an analytical solution to calculate the output.
Notice that, with the process in the question, each item of the root array is completely deleted before moving on to the next item. Using the original example [[1,2],[3,[4,5]]
, the [1,2]
subarray is fully deleted before [3,[4,5]]
is touched. This means that while processing [1,2]
, the sizes of the intermediate arrays at each step is the same as those while processing [1,2]
as a root, but plus 1 because we have to count [3,[4,5]]
[[1, 2], [3, [4, 5]]]
[1, 2, [3, [4, 5]]] (size: 3) | [1,2] (size: 2)
[2, [3, [4, 5]]] (size: 2) | [2] (size: 1)
[[3, [4, 5]]] (size: 1) | [] (size: 0)
Take another example from the test cases
[[6, 3, [1, 3, 4]], 4, [2, 3, 9, [5, 6]]]
[6, 3, [1, 3, 4], 4, [2, 3, 9, [5, 6]]] (size: 5) | [6, 3, [1, 3, 4]] (size: 3)
[3, [1, 3, 4], 4, [2, 3, 9, [5, 6]]] (size: 4) | [3, [1, 3, 4]] (size: 2)
[[1, 3, 4], 4, [2, 3, 9, [5, 6]]] (size: 3) | [[1, 3, 4]] (size: 1)
[1, 3, 4, 4, [2, 3, 9, [5, 6]]] (size: 5) | [1, 3, 4] (size: 3)
[3, 4, 4, [2, 3, 9, [5, 6]]] (size: 4) | [3, 4] (size: 2)
[4, 4, [2, 3, 9, [5, 6]]] (size: 3) | [4] (size: 1)
[4, [2, 3, 9, [5, 6]]] (size: 2) | [] (size: 0)
The size difference is 2 here because there are 2 items after the item being processed ([6, 3, [1, 3, 4]]
).
This shows that this problem can be solved with a recursive algorithm
f([1, 2]) = [2, 1, 0]
f([3, [4, 5]]) = [2, 1, 2, 1, 0]
[2, 1, 0][2, 1, 2, 1, 0]
+ [2, 1, 0]
--------------------------------
f([[1, 2], [3, [4, 5]]]) = [2, 3, 2, 1, 2, 1, 2, 1, 0]
More precisely, the output of processing an array consists of:
- The initial length of the array, then
- For each item, the result of processing that item, plus adding the number of items after it to each element.
Naive, readable implementation
function f(value) {
if (value !== undefined) {
return [
value.length,
...value.flatMap((item, index) => f(item).map((n) => n + value.length - index - 1))
]
}
return [0]
}
Golfing
First, of course, is to apply basic golfing techniques
// 70 bytes
f=v=>v?[v.length,...v.flatMap((u,j)=>f(u).map($=>$+v.length-j-1))]:[0]
Then, since leaves are undefined
, we can actually use default argument to treat leaves as []
and merge the two branches
// 69 bytes
f=(v=[])=>[v.length,...v.flatMap((u,j)=>f(u).map($=>$+v.length-j-1))]
Then, instead of mapping a second time to add the "base" value v.length-j-1
, we can make f
accept a second argument for a value to add to everything.
// 67 bytes
f=(v=[],i=0)=>[v.length+i,...v.flatMap((u,j)=>f(u,v.length+i-j-1))]
Next, we can pull i
up to the global scope and mutate it instead of passing it around and using a lengthy expression to calculate the base
// 53 bytes
i=0;f=(v=[])=>[i+=v.length,...v.flatMap(u=>f(u,i--))]
Finally, we can move the i--
decrement into f
so that, instead of decrementing at each flatMap
iteration, we just decrement i
at the start of f
.
// 45 bytes
i=1;f=(v=[])=>[i+=v.length-1,...v.flatMap(f)]
BUT, this breaks because the global variable i
is changed after calling f
, which is forbiddened. Specifically, i
is decremented by 1 for each root call to f
. Before the change, i
is decremented by 1 by one per child while looping in flatMap
, but now i
is decremented by 1 per call (i.e. per node), and the root is the only node that is not a child.
To counter this, we need to change the increment to "number of children" (instead of "number of children - 1") but only for the root node. This is doable by noticing that i
is at its initial value only at the start of a root f
call and after processing the last leaf. So we can initialize i
to 0 and when we increment i
, we increment by "number of children" if i
is 0 but by "number of children - 1" otherwise.
// 47 bytes
i=0;f=(v=[])=>[i+=v.length-!!i,...v.flatMap(f)]
[[],[[[]]],[]] -> [3, 2, 2, 2, 1]
\$\endgroup\$