Chain words crossword-style
ANSI C, 385 390 Characters
int N,a=1,x,y,d=1,u,k,l;int main(int c,char**v){for(;a<c;)N+=strlen(v[a++]);int H=N*2,W=N*4,m=H,n=N,q=m,w=n;char*p,F[W][H],*o;memset(F,32,W*H);for(a=1;a<c;a++){q=(x=m)<q?m:q;w=(y=n)<w?n:w;m=-1;for(p=v[a];*p;p++){F[x][y]=*p;if(m<0&&a<c-1&&(o=strchr(v[a+1],*p))){u=o-v[a+1];m=d?x:x-u*2;n=d?y-u:y;}if(d)x+=2;else y++;}d=!d;}for(l=w;l<H;l++){for(k=q;k<W;)putchar(F[k++][l]);putchar(10);}}
Call it like this: ./crossword This site graduated finally
Ungolfed version:
int N,a=1,x,y,d=1,u,k,l;
int main(int c, char **v) {
for(;a<c;)
N+=strlen(v[a++]);
int H = N*2, W = N*4, m = H, n = N, q=m, w=n;
char *p,F[W][H], *o;
memset(F, 32, W*H);
for (a=1; a < c; a++) {
q=(x=m)<q?m:q;
w=(y=n)<w?n:w;
m=-1;
for (p=v[a]; *p; p++) {
F[x][y] = *p;
if (m<0&&a<c-1&&(o = strchr(v[a+1], *p))) {
u = o-v[a+1];
m = d ? x : x-u*2;
n = d ? y-u : y;
}
if (d) x+=2; else y++;
}
d=!d;
}
for (l = w; l < H; l++) {
for (k = q; k < W;)
putchar(F[k++][l]);
putchar(10);
}
}
Thank you tucuxi for the tips!
JavaScript (ES6) 253
As an anonymous function with an array parameter
z=>(z.map((w,i)=>(i&&[...p].some((c,j)=>~(k=w.search(c))?i&1?[y-=k,x+=j]:[y+=j,x-=k]:0),[p=w,x<t?t=x:x,y<u?u=y:y]),t=u=x=y=0).map(([w,x,y],i)=>{x-=t,y-=u;for(c of w)(o[y]=o[y]||[])[x]=c,i&1?y++:x++},o=[]),o.map(r=>[...r].map(x=>x||' ').join` `).join`
`)
F=z=>(z.map((w,i)=>(i&&[...p].some((c,j)=>~(k=w.search(c))?i&1?[y-=k,x+=j]:[y+=j,x-=k]:0),[p=w,x<t?t=x:x,y<u?u=y:y]),t=u=x=y=0).map(([w,x,y],i)=>{x-=t,y-=u;for(c of w)(o[y]=o[y]||[])[x]=c,i&1?y++:x++},o=[]),o.map(r=>[...r].map(x=>x||' ').join` `).join`
`)
// Less golfed
F=z=>(
z.map( // Step 1, find intersection points and relative position
(w,i)=>(
i && // for each word after thw first, find position respect the previous word
[...p].some((c,j)=> // scan prec word using .some to exit at the first intersection found
~(k=w.search(c)) // search current char of p inside w
?i&1 // calc position, odd is vertical, even is horizontal
?[y-=k, x+=j] // returning an array so to have a truthy value
:[y+=j, x-=k] // returning an array so to have a truthy value
:0 // false = not found, continue the scan
),
[p=w, // set preceding word
x<t?t=x:x, // keep trace of min x
y<u?u=y:y // keep trace of min y
] // meanwhile, return word, x and y to be used in next step
), t=u=x=y=0 // initializations
)
.map(([w,x,y],i)=>{ // Step 2, put char into the output array
x-=t,y-=u; // normalize position respect to min values
for(c of w) // for each char in word, set in the output array at the right place
(o[y]=o[y]||[])[x]=c,
i&1?y++:x++ // increment x or y, again odd is vertical, even is horizontal
}, o=[] // initialization of output array
),
// Step 3, add the missing spaces and newlines
o.map(r=>[...r].map(x=>x||' ').join` `).join`\n`
)
O.textContent=F(["This", "site", "graduated", "finally"])
<pre id=O></pre>