## Introduction

Consider two non-empty integer arrays, say A = [0 3 2 2 8 4] and B = [7 8 7 2]. To perform alignment addition on them, we do the following:

1. Repeat each array enough times to have total length $$\\text{lcm(length(A), length(B))}\$$. Here $$\\text{lcm}\$$ stands for lowest common multiple.

A -> [0 3 2 2  8 4][0 3  2 2 8 4]
B -> [7 8 7 2][7 8  7 2][7 8 7 2]

2. Perform element-wise addition on the repeated arrays, and cut the result at every position where there's a cut in either of them.

A -> [0  3 2 2   8  4][0 3  2  2  8 4]
B -> [7  8 7 2][ 7  8  7 2][7  8  7 2]
-> [7 11 9 4][15 12][7 5][9 10 15 6]

3. This array of arrays is your result.

Your inputs are two non-empty arrays of integers, and your output shall be the result of their alignment addition, as defined above. The inputs and output can be in any reasonable format. You don't have to worry about integer overflow when performing the addition.

## Rules and scoring

You can write a full program or a function. The lowest byte count wins.

## Test cases

[1] [4] -> [[5]]
[1,2,-3,-4] [15] -> [[16],[17],[12],[11]]
[0,-4] [2,1,0,-3] -> [[2,-3],[0,-7]]
[0,3,2,2,8,4] [7,8,7,2] -> [[7,11,9,4],[15,12],[7,5],[9,10,15,6]]
[18,17,16] [-1,-2,-3,-4] -> [[17,15,13],[14],[16,14],[15,13],[15],[16,14,12]]
[18,17,16,15] [-1,-2,-3,-4] -> [[17,15,13,11]]
[1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7],[6,7,3,2],[7],[6,7,6,7,6],[7,3,2],[7,6],[7,6,7,6,7],[3,2],[7,6,7],[6,7,6,7,3],[2],[7,6,7,6],[7,6,7,3,2]]
[1,1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7,6],[7,3,2],[7,6,7],[6,7,6,7,3,2]]
[1,1,1,1,1,1,1] [6,5,6,5,6,5,6,2,1] -> [[7,6,7,6,7,6,7],[3,2],[7,6,7,6,7],[6,7,3,2],[7,6,7],[6,7,6,7,3,2],[7],[6,7,6,7,6,7,3],[2],[7,6,7,6,7,6],[7,3,2],[7,6,7,6],[7,6,7,3,2],[7,6],[7,6,7,6,7,3,2]]
• C doesn't have a way to know an array's length -- can I request the length of the array as an argument, or have it stored at the beginning of the array?
– cat
Commented Dec 17, 2016 at 16:47
• @cat You can take the lengths as extra arguments, if there's no other way of getting them. Commented Dec 17, 2016 at 17:11

## JavaScript (ES6), 101 99 bytes

Takes input as 2 arrays. Returns a string.

f=(a,b,j=0,s='')=>a.map((v,i)=>(s+=i*j?' ':s&&'][',s+=b[j]+v,j=++j%b.length))|j?f(a,b,j,s):[${s}] ### How it works We iterate on the first array a with a pointer i while updating another pointer j into the second array b. The sums a[i] + b[j] are appended to the output string s. A separator is inserted each time i == 0 or j == 0. We repeat this process until j is back exactly at the beginning of b at the end of an iteration. Note: When the | operator is applied, a.map(...) is coerced to either NaN (if a contains more than one element) or the current value of j (if a contains exactly one element). Therefore, a.map(...)|j == j in all cases and is safe to use here. ### Test cases f=(a,b,j=0,s='')=>a.map((v,i)=>(s+=i*j?' ':s&&'][',s+=b[j]+v,j=++j%b.length))|j?f(a,b,j,s):[${s}]

console.log(f([1], [4]));
console.log(f([1,2,-3,-4], [15]));
console.log(f([0,-4], [2,1,0,-3]));
console.log(f([0,3,2,2,8,4], [7,8,7,2]));
console.log(f([18,17,16], [-1,-2,-3,-4]));
console.log(f([18,17,16,15], [-1,-2,-3,-4]));
console.log(f([1,1,1,1,1], [6,5,6,5,6,5,6,2,1]));
console.log(f([1,1,1,1,1,1], [6,5,6,5,6,5,6,2,1]));
console.log(f([1,1,1,1,1,1,1], [6,5,6,5,6,5,6,2,1]));

• I have not even tried to understand the answer, +1 for the note. I'll copy and keep it to paste when needed Commented Dec 17, 2016 at 9:18

a#b=a%b where(c:d)%(e:f)|(x:y)<-d%f=(c+e:x):y;[]%[]=[[]];c%[]=[]:c%b;_%d=[]:a%d

My first version was the same in more readable layout:

a#b=a%b where
(c:d)%(e:f)|(x:y)<-d%f=(c+e:x):y
[]%[]=[[]]
c%[]=[]:c%b
_%d=[]:a%d

Using a local definition to avoid having to give (%) extra arguments for a and b. Amazingly, this is almost the same solution given at almost the same time as @nimi's, from whom I took the idea of using only one line for the local definition.

Usage:

*Main> [0,3,2,2,8,4] # [7,8,7,2]
[[7,11,9,4],[15,12],[7,5],[9,10,15,6]]
• Oh, that's a nice way to prepend the sum to the first element of the list. Far shorter than my cumbersome !.
– nimi
Commented Dec 16, 2016 at 19:39

# PHP, 126 120 bytes

function($a,$b){do{$c[$j][]=$a[$i%$x=count($a)]+$b[$i%$y=count($b)];++$i%$x&&$i%$y?:$j++;}while($i%$x|$i%$y);return$c;};

Try it here!

Anonymous function that returns the resulting array of arrays.

Essentially, we loop through the contents of both of our arrays, modding our iterator by the length of the array to simulate 'copying' them. Taking each of the values from the arrays, we sum them and add them to an array in $c. If we reach the end of one of our input arrays (a split, in terms of the challenge), we start assigning into a new array in$c.

J€ỊÇœṗÇḊ

Try it online!

### How it works

ṁ€L€æl/$S Helper link. Argument [X, Y] (arrays of integers).$   Combine the two links to the left into a monadic chain.
L€       Length each; yield the lengths of X and Y.
æl/    Reduce by least common multiple.
ṁ€         Mold each; cyclically repeat the elements of X and Y to extend them
to length lcm(length(X), length(Y)).
S  Compute the sum of the extended X and Y arrays.

J€ỊÇœṗÇḊ   Main link. Argument [A, B] (arrays of integers).

J€         Indices each; replace A and B by the arrays of there 1-based indices.
Ị        Insignificant; map 1 to itself, all other indices to 0.
Ç       Apply the helper link to the result.
This yield a Boolean array with a 1 (or 2) at all indices where a new
repetition of A or B (or both) begins.
Ç    Apply the helper link to [A, B].
œṗ     Partition; break the result to the right at truthy elements (1 or 2) in
the result to the right.
Ḋ   Dequeue; remove the first element of the partition (empty array).

# Python 3.5 - (146137134130+12) = 142 Bytes

import math
def s(a,b):
l,k,*r=map(len,[a,b])
for i in range(l*k//math.gcd(l,k)):
r+=a[i%l]+b[i%k],
if i%k==k-1or i%l==l-1:print(r);r=[]

I cannot figure out how to put the whole for loop in one line.

Edits:

• This gives an error for me. The gcd function is in fractions, not math. Commented Dec 16, 2016 at 11:10
• @Zgarb the gcd in fractions module is deprecated, you can check the change here . I guess rexter is using the old version 3.4.3. Commented Dec 16, 2016 at 11:30
• Neat, I didn't know about this change. You should mark the language as "Python 3.5" though, since it doesn't work in 3.4 or earlier. Also, you can drop the parentheses around l*k and have print(r);r=[] on the last line. Commented Dec 16, 2016 at 11:30
• Are you sure your byte count is correct? I think there're only 145 bytes. Commented Dec 16, 2016 at 12:42
• I'm getting 142 bytes. Are you using Windows? Windows usually counts newlines as 2 bytes each, but here each newline is counted as a single byte. Commented Dec 17, 2016 at 3:23

# Python 2, 119 bytes

a=input()
i,v,l=0,list(a),len
while 1:q=l(v[0])>l(v[1]);print map(sum,zip(*v)[i:]);i=l(v[q]);v[q]+=a[q];1/(i-l(v[q^1]))

Takes input from stdin as two tuples separated by comma, outputs resulting lists to stdout. Terminates by raising the ZeroDivisionError exception, since that seems to be allowed.

For example, if the input is (0, 3, 2, 2, 8, 4), (7, 8, 7, 2), the program will print

[7, 11, 9, 4]
[15, 12]
[7, 5]
[9, 10, 15, 6]

to stdout and the exception traceback to stderr.

# J, 34 32 bytes

[:(<;.1~*)/[:+/*.&#$&>,:&(;2>#\) Try it online! ## Explanation [:(<;.1~*)/[:+/*.&#$&>,:&(;2>#\)  Input: array A (LHS), array B (RHS)
#\   Length of each prefix of A and B
2>     Less than 2
;       Link each with A and B
,:&         Pair them
#               Length of A and B
*.&                LCM of the lengths
&>            For each box
$Reshape it to the LCM of the lengths [:+/ Reduce by addition [: / Reduce by * Sign of RHS <;.1~ Box each partition of LHS # Haskell, 166 bytes This is probably not the most elegant approach: Basically the function ? creates one list of the needed length with thesums, and % is cutting this sum up again. ! is the final function that merges those two. l=length a?b=take(lcm(l a)$l b)$zipWith(+)(cycle a)$cycle b
l%(i:ind)|l==[]=[]|1>0=take i l:(drop i l)%(map(+(-i))ind)
a!b=(a?b)%[k|k<-[1..],kmodl a<1||kmodl b<1]
• You can replace ind by k or something, and there are some unnecessary parentheses around drop i l and map(+(-i))ind. Consider also having two cases for %, with pattern matching on l. Commented Dec 16, 2016 at 11:33

# [PHP], 183152 135 bytes

function O($A,$B){while($f<2){$O[$k][]=$A[+$i]+$B[+$j];$f=0;isset($A[++$i])?:$i=!++$k|!++$f;isset($B[++$j])?:$j=!++$k|!++$f;}return$O;} Nice version: function O($A,$B) { while($f<2) {
$O[$k][]=$A[+$i]+$B[+$j];
$f=0; isset($A[++$i])?:$i=!++$k|!++$f;
isset($B[++$j])?:$j=!++$k|!++$f; } return$O;
}

Output:

array (size=4)
0 =>
array (size=4)
0 => int 7
1 => int 11
2 => int 9
3 => int 4
1 =>
array (size=2)
0 => int 15
1 => int 12
2 =>
array (size=2)
0 => int 7
1 => int 5
3 =>
array (size=4)
0 => int 9
1 => int 10
2 => int 15
3 => int 6
• Draw even with me using these tweaks: $i=$j=$k=0; is unnecessary if you use +$i etc. for the array indexes in the appending assignment (-8 bytes). $i++;if(!isset($A[$i])){$i=0;$k++;} --> isset($A[++$i])?:$i=!++$k; (-9, twice).$i==0&&$j==0&&!isset() --> !$i&!$j&!isset() (-6). return$O; needs no space (-1). Commented Dec 16, 2016 at 15:28
• @Titus can't remove $i=$j=0; part since first values from arrays won't be correct. I've modified logic a little so not sure how to implement ternary operators in this case. Thanks for ++$i advices. – Dexa Commented Dec 16, 2016 at 16:18 • Try unset($i);$A[+$i]. The + will cast null to integer 0. Commented Dec 16, 2016 at 16:26
• if(!isset($A[++$i])){$i=0;++$k;++$f;} --> isset($A[++$i])?:$i=!++$k|!++$f; still saves 5 bytes each. Save one more with $f<2 instead of$f!=2. and another two with while($f=$f<3){...} instead of while($f<2){$f=0;...} (initializes and resets $f to 1 unless it´s incremented twice) Commented Dec 16, 2016 at 16:39 • @Titus Thanks a lot, it is shorter now. – Dexa Commented Dec 16, 2016 at 16:52 # PowerShell, 147 145 bytes param($a,$b)$o=@{};do{$o[+$j]+=,($a[+$i%($x=$a.count)]+$b[$i++%($y=$b.count)]);if(!($i%$x-and$i%$y)){$j++}}until(($x,$y|?{!($i%$_)}).count-eq2)$o

Try it online!

(Golfing suggestions welcome. I feel there's probably another 10 to 15 bytes that can be squeezed out of this.)

Takes input as two explicit arrays (with the @(...) syntax) as command-line arguments. Returns a hashtable of the resulting arrays, because multidimensional arrays in PowerShell can get weird, and this is more consistent. Sets some initial variables, then enters a do/until loop again, with the conditional being until $i is the lcm of the array counts. Each loop iteration, we add the corresponding$a and $b values together, treat it as an array ,(...) before adding it into the hashtable$o at the appropriate spot $j. The array encapsulation is necessary to prevent arithmetical addition -- this forces the += to overload to array concatenation instead. Then, a conditional on$x and $y (the counts) to determine if we're at an array edge - if so, we increment$j.

Finally, we leave $o on the pipeline and output is implicit. (NB: Due to how PowerShell enumerates hashtables with the default Write-Output, this tends to be output "backward"; as in, the "0th" resultant array is on the "bottom" of the output. The hash itself is fine, and would be used just fine if you e.g., encapsulated this code in a return variable ... it just looks odd when it's printed.) Saved 2 bytes by moving$x and $y into the array indexing rather than separate (saved two semicolons). # Python 2, 113 bytes a,b=input() i=m=n=0;r=[] while(not i)+m+n:r+=[[]]*(not m*n);r[-1]+=[a[m]+b[n]];i+=1;m=i%len(a);n=i%len(b) print r • Could the nots be <1s instead? Commented Dec 17, 2016 at 10:15 ## Python 3.5, 210176173169 158 Bytes def f(a,b): x=[];e=f=0 while 1: if e==len(a): print(x);x=[];e=0; if f==len(b):break if f==len(b):print(x);x=[];f=0 x+=a[e]+b[f],;e+=1;f+=1 Takes two lists as input and prints all the lists. Its my first answer and I don't know how to golf yet. The basic idea I've used is to have two counters for each list which indicate a split and a current list where the added values are appended onto; as soon as a split is encountered, we print the current list and make a new empty one. • Saved 34 bytes: Thanks to Dennis and TimmyD • Saved 3 bytes: was using c and d for len(a) and len(b), but turns out they weren't useful • Saved 4 bytes: Thanks to orlp, removed unwanted paranthesis • Saved 11 bytes: rearranged some blocks and crunched them down • Hi, and welcome to Programming Puzzles & Code Golf! Non-competing means something else here; you should remove that. You can save quite a few bytes by eliminating whitespace. For example, lines 2 to 5 can become x=[];c=len(a);d=len(b);e=f=0. Also, true can become 1, and x.append(a[e]+b[f]) can become x+=a[e]+b[f],. Commented Dec 16, 2016 at 16:40 • Welcome to PPCG! In addition to Dennis' specific tweaks, check out Tips for Golfing in Python to get some more general hints and tricks. Commented Dec 16, 2016 at 16:58 • if and while statements do not need parenthesis. – orlp Commented Dec 16, 2016 at 23:10 ## Racket 373 bytes (let*((lg length)(fl flatten)(ml make-list)(t rest)(r reverse)(m modulo)(o cons)(ln(lg l))(jn(lg j))(c(lcm ln jn))(l2(fl(ml(/ c ln)l))) (j2(fl(ml(/ c jn)j)))(ll(for/list((a l2)(b j2))(+ a b))))(let p((ll ll)(ol '())(tl '())(n 0))(cond[(empty? ll)(t(r(o(r tl)ol)))] [(or(= 0(m n ln))(= 0(m n jn)))(p(t ll)(o(r tl)ol)(take ll 1)(+ 1 n))][(p(t ll)ol(o(first ll)tl)(+ 1 n))]))) Ungolfed: (define(f l j) (let* ((ln (length l)) (jn (length j)) (c (lcm ln jn)) (l2 (flatten (make-list (/ c ln) l))) (j2 (flatten (make-list (/ c jn) j))) (ll (for/list ((a l2)(b j2)) (+ a b)))) ; TO CUT LIST INTO PARTS: (let loop ((ll ll) (ol '()) (templ '()) (n 0)) (cond [(empty? ll) (rest (reverse (cons (reverse templ) ol)))] [(or (= 0 (modulo n ln)) (= 0 (modulo n jn))) (loop (rest ll) (cons (reverse templ) ol) (list (first ll)) (add1 n))] [(loop (rest ll) ol (cons (first ll) templ) (add1 n))])))) Testing: (f '[1] '[4]) (f '[1 2 -3 -4] '[15]) (f '[0 3 2 2 8 4] '[7 8 7 2]) Output: '((5)) '((16) (17) (12) (11)) '((7 11 9 4) (15 12) (7 5) (9 10 15 6)) Clojure, 280 206 bytes (fn[a b](let[A(count a)B(count b)Q quot](map #(map last %)(partition-by first(take-while #((% 0)2)(map-indexed(fn[i s][[(Q i A)(Q i B)(or(= i 0)(>(mod i A)0)(>(mod i B)0))]s])(map +(cycle a)(cycle b)))))))) Well this makes a lot more sense. Generating the element-wise sum, adding positional metadata, taking while we haven't repeated yet and putting the sum value to each partition. (def f (fn[a b] (let[A(count a)B(count b)Q quot] (->> (map +(cycle a)(cycle b)) (map-indexed (fn [i s][[(Q i A)(Q i B)(or(= i 0)(>(mod i A)0)(>(mod i B)0))]s])) (take-while #((% 0)2)) (partition-by first) (map #(map last %)))))) Original: I'm hoping to improve this but this is the sortest one I have for now. (fn[a b](let [C cycle o count c(take-while #(or(=(% 0)0)(>(% 1)0)(>(% 2)0))(map-indexed(fn[i[A B]][i(mod i(o a))(mod i(o b))(+ A B)])(map(fn[& v]v)(C a)(C b))))](map #(map last %)(partition-by first(map(fn[p c][p(last c)])(reductions + (map #(if(or(=(% 1)0)(=(% 2)0))1 0)c))c))))) Ungolfed and verbose: (def f (fn[a b] (let [c(->> (map (fn[& v]v) (cycle a) (cycle b)) (map-indexed (fn[i[A B]][i (mod i(count a)) (mod i(count b)) (+ A B)])) (take-while #(or(=(% 0)0)(>(% 1)0)(>(% 2)0))))] (->> (map (fn[p c][p(last c)]) (reductions +(map #(if(or(=(% 1)0)(=(% 2)0))1 0)c)) c) (partition-by first) (map #(map last %)))))) Starts by "merging" an infinite cycle of collections a and b, adds metadata on each element's index within the collection, takes until both sequences start from index 0 again. This collection c is then merged with partition data (a cumulative sum of ones and zeroes), partitioned and the last element (being sum of items) is selected. I think for significant improvements a totally different approach is required. # PHP, 150121 119 bytes function($a,$b){while($i<2|$x|$y)$r[$k+=!($x=$i%count($a))|!$y=$i++%count($b)][]=$a[$x]+$b[$y];array_pop($r);return$r;}

anonymous function takes input as arrays.

breakdown

while($i<2|$x|$y) // loop while either$a or $b has NO cut$r[
// if either $a or$b has a cut, increment $k; post-increment$i
$k+=!($x=$i%count($a))|!$y=$i++%count($b) // append current$a + current $b to$r[$k] ][]=$a[$x]+$b[$y]; array_pop($r);  // $r has one element too much; remove it return$r;

# C++14, 206 bytes

As unnamed generic lambda, requiring input containers P,Q and output container R to be like vector<vector<int>>.

[](auto P,auto Q,auto&R){R.clear();auto a=P.begin(),b=Q.begin(),x=P.end(),y=Q.end();auto A=a,B=b;do{R.emplace_back();while(a!=x&&b!=y)R.back().push_back(*a+++*b++);a=a==x?A:a;b=b==y?B:b;}while(a!=A||b!=B);}

Ungolfed and usage:

#include<vector>
#include<iostream>

using namespace std;

auto f=
[](auto P,auto Q,auto&R){
R.clear();               //just clear the output to be sure
//a and b are the iterators, x and y is the end
auto a=P.begin(),b=Q.begin(),x=P.end(),y=Q.end();
//just some abbreviations for .begin()
auto A=a,B=b;
do{
while(a!=x&&b!=y)      //while not at the end of one vector
a=a==x?A:a;            //reset if at the end
b=b==y?B:b;
}while(a!=A||b!=B);     //if both were resetted, then finish
}
;

int main(){
vector<int> A = {0, 3, 2, 2, 8, 4};
vector<int> B = {7, 8, 7, 2};
vector<vector<int>> R;
f(A,B,R);
for (auto c:R){
for (int x:c)
cout << x << ", ";
cout << endl;
}
cout << endl;
}

## Mathematica 112 Bytes

This could probably be improved upon. The idea is to create a 2D array with the second element used to track the lessor of the counter i mod the length of each input array.

Split[Table[{#[[1,(m=Mod[i,d=Length/@#,1])[[1]]]]+#[[2,m[[2]]]],Min@m},{i,LCM@@d}],#2[[2]]>#1[[2]]&][[;;,;;,1]]&

Usage

%@{{0,3,2,2,8,4},{7,8,7,2}}

## JavaScript (ES6), 131 bytes

(a,b,g=(r,[n,...d]=a,[m,...e]=b,s=[])=>1/n?1/m?g(r,d,e,[...s,n+m]):g([...r,s],[n,...d]):1/m?g([...r,s],a,[m,...e]):[...r,s])=>g([])

Slightly ungolfed:

(a,b,r=[],[n,...d]=a,[m,...e]=b,s=[])
=>1/n?1/m?f(a,b,r,d,e,[...s,n+m])
:f(a,b,[...r,s],[n,...d],b,[])
:1/m?f(a,b,[...r,s],a,[m,...e],[])
:[...r,s]
• If both arrays d and e contain numbers, the sum of the first number is appended to s and the remaining elements are processed recursively
• If one of the arrays contains numbers, the array of sums s is appended to the result r and the other array is reset to its initial array
• If both arrays are empty then simply return the result with the last sums appended.

Sadly this solution doesn't have the ruthless efficiency of @Arnauld's, but at least I think it's a beautiful solution.

# Jelly, 17 bytes

Ẉæl/
ẈḍⱮÇ§kṁ€ÇSƊṖ

Try it online!

## How it works

Ẉæl/ - Helper link. Takes an array [A, B] on the left
Ẉ    - Lengths; [len(A), len(B)]
/ - Reduce by:
æl  -   LCM
This yields R := lcm(length(A), length(B))

ẈḍⱮÇ§kṁ€ÇSƊṖ - Main link. Takes [A, B] on the left
Ẉ            - [len(A), len(B)]
Ç         - Call the helper link on [A, B]
Ɱ          - Over each integer i = 1, 2, ..., R:
ḍ           -   Yield [x, y] where:
x = 1 if len(A) % i == 0 else 0
y = 1 if len(B) % i == 0 else 0
§        - For each pair, yield 0 if x = y = 0 else a non-zero element
Ɗ  - To [A, B]:
Ç    -   Yield R
€     -   Over each element A, B:
ṁ      -     Mold to length R
S   -   Columnwise sums
k       - Partition this array on the right at the non-zero indexes on the left
Ṗ - Remove the trailing empty array