function board = solver(words, weights, n, penalty)
%initialize board and some other stuff
board = zeros(n);
forbidden=-1;
%word counter
m=1;
if penalty<1
step=1;
else
step=2;
end
%sort words first by weight then by length
[~,idx_w]=sort(weights,'descend');
words=words(idx_w);
l_w=cellfun(@length,words);
[l_w,idx_l]=sort(l_w);
words=words(idx_l);
if step*length(weights)<n
%put words in rows
for k=1:step:step*length(weights)
board(k,1:length(words{m}))=words{m};
m=m+1;
end
else
%arrange words in rows
for r=1:step:n
%most important word first
fillto=length(words{1});
board(r,1:fillto)=words{1};
words(1)=[];
l_w(1)=[];
fillfrom=fillto+1;
%fill rest of row
while fillfrom+min(l_w)<=n
board(r,fillfrom)=forbidden;
m=find((l_w<=n-fillfrom),1);
fillto=fillfrom+length(words{m});
board(r,(fillfrom+1):fillto)=words{m};
words(m)=[];
l_w(m)=[];
fillfrom=fillto+1;
end
end
%try to slot in some vertical words
%only words with odd length work in this scheme (apart from a few cases
%that are too complicated for me... :) )
words(2*round(l_w/2)==l_w)=[];
for c=1:step:n
for w=1:length(words)
curr_word=words{w};
matching_first_letter=find(curr_word(1)==board(:,c),1);
if(isempty(matching_first_letter)||(length(curr_word)-1+matching_first_letter)>n)
break;
end
all_fit=1;
for b=(1+step):step:length(curr_word)
if(board(matching_first_letter-1+b,c)~=curr_word(b))
all_fit=0;
break;
end
end
if(all_fit)
board(matching_first_letter+(0:(length(curr_word)-1)),c)=curr_word;
end
end
end
end
board(board==forbidden)=0;
end
|