# Jam don't add like that

## APL, 44 bytes

{1=≡⍺⍵:⍺+⍵⋄=/∆←|≡¨⍺⍵:⊃∇¨/↓↑⍺⍵⋄</∆:⍺∘∇¨⍵⋄⍵∇⍺}


APL's + distributes over arrays as well, but in a different enough manner that this can't really be used. However, there is a built-in depth function (≡).

Explanation:

• 1=≡⍺⍵:⍺+⍵: if the depths of ⍺ ⍵ are both zero (and therefore the depth of ⍺ ⍵ is 1), add them.
• ∆←|≡¨⍺⍵: take the absolute of the depth of both ⍺ and ⍵ and store them in ∆. (≡ gives a negative value if not all elements have the same depth.)
• =/∆: if they have the same depth:
• ↓↑⍺⍵: pad the shortest array with zeroes to match the longer array
• ⊃∇¨/: distribute the function over both arrays
• </∆: if the depth of ⍺ is less than that of ⍵:
• ⍺∘∇¨⍵: bind ⍺ and then map over ⍵
• ⍵∇⍺: if nothing else (so ⍵ is deeper than ⍺), swap the arguments and try again.

### Mathematica, 122 bytes

d=Depth
x_~f~y_/;d@x>d@y:=y~f~x
x_~f~y_/;d@x<d@y:=x~f~#&/@y
x_~f~y_=x+y


Defines a recursive function f which computes the sum. Making use of Mathematica's pattern matching, this function is made up of four separate definitions:

x_~f~y_/;d@x>d@y:=y~f~x


If the depth of x is greater than that of y, swap the arguments so that we only have to handle distribution in one direction (which we can do, since addition is commutative).

x_~f~y_/;d@x<d@y:=x~f~#&/@y


If the depth of x is less thann that of y, replace each value # in y with f[x,#], which takes care of the distribution for arguments of unequal depth.

x_List~f~y_:=MapThread[f,{x,y}~PadRight~Automatic]


Otherwise, if one argument is a list (which implies that the other also is a list, since we know they have the same depth), we put both arguments in a list, pad them to the same length with PadRight[..., Automatic] (which simply fills up a ragged array with zeros to make it rectangular), and then use MapThread to apply f to corresponding pairs from the two lists.

And finally, the base case:

x_~f~y_=x+y


If none of the other patterns match, we must be trying to add two numbers, so we just do that.

data L=S Int|V{v::[L]}
d(V z)=1+maximum(d<$>S 0:z);d _=0 S x!S y=S$x+y
x!y|d x<d y=V$(x!)<$>v y|d x>d y=y!x|1<2=V$v x#v y (x:a)#(y:b)=x!y:a#b;a#b=a++b  ### Explanation The first line defines an algebraic data type L, which is either a Scalar (containing an Int) or a Vector (containing a list of Ls, accessed using a record getter v, which is a partial function L → [L].) The second line defines the depth function: the depth of a Vector is one plus its maximum depth. I prepend S 0 to the values in the vector, so that depth [] == 1 + maximum [depth (S 0)] == 1. The depth of “anything else” (a scalar) is 0. The third line defines the base case for ! (the addition function): the sum of scalars is simply a scalar. The fifth line defines a variant of zipWith (!) that just picks elements from the longest list when one of them is empty. The fourth line is split in three cases: x!y | d x<d y = V$(x!)<$>v y | d x>d y = y!x | True = V$v x#v y

• If the depth of x is strictly less than the depth of y, map (x!) over the elements of y. (The use of v is guaranteed to be valid, as d(y) ≥ 1.)

• If the depth of x is strictly greater, flip the arguments and restart.

• If their depths are equal, zip the arguments together with (!). (The use of v is guaranteed to be valid, as the case d(x) = d(y) = 0 was handled as a base case.)

### Test cases

instance Show L where
show (S x) = show x
show (V x) = show x

lArg = V [S 1, V [S 2, V [S 3, V [S 4]]]]
rArg = V [S 10, V [S 20]]


Then show (lArg ! rArg) == "[[11,[21]],[[12,[22]],[13,[24]]]]".