function board = solver(words, weights, N, penalty)
nws = numel(words);
% [weights,idx] = sort(weights,'descend');
% words = words(idx);
lengths = cellfun('length',words);
sumw = sum(weights);
[board, score] = solver_james1 (words, weights, N, penalty, lengths, nws, sumw);
end
function [board, result] = solver_james1(words, weights, n, penalty, wordlengths, nwords, total)
board = zeros(n);
[B,index] = sortrows([wordlengths' weights'],[1 -2]); % index is wordsFromBIndex
last2letterword = find(B(:,1)>2,1)-1;
%words2 = words(index(1:last2letterword));
w2l = index(1:last2letterword)'; % should be row vector for for
isUnplayed = true(1,nwords);
hopeless = false(1,nwords);
[C,alphaix]=sortrows(cell2mat(words(w2l)')); % so char(C) = char(words{w2l(alphaix)}) % alphaix is WfromC
%wFromC=w2l(alphaix); % gives index in original words
points = 0;
c=1;
r=1;
L = 2; % dim of sq
while r+L-1 <= n,
% try excluding words with letter frequencies of 1
% ordering words by first and second letter would help
sq = zeros(2);
if ~isempty(w2l)
C1 = C(:,1);
[sq, isUnplayed, hopeless] = press2(words, isUnplayed, hopeless, w2l, C1, alphaix,sq);
end
if ~sq,
break; % no more 2x2s
end
board(r+(0:L-1),c+(0:L-1)) = sq;
c=c+L+1;
if c > n-(L-1),
r =r+L+1;
c=1;
end
end
points = points + sum(weights(~isUnplayed));
% eliminate words that have already been played
[B,index] = sortrows([wordlengths(isUnplayed)' weights(isUnplayed)'],[1 -2]);
words = words(isUnplayed);
nwords = numel(words);
isUnplayed2 = true(1,nwords);
k=1;
% play remaining unused 2 letter words here?
% index of last word to play in current row
stop_index = min(nwords, n*k-c+1); % check that we haven't run out of words
start_index = 1;
while (r+B(stop_index,1)-1) <= n, % if the new row fits
words_left = stop_index - start_index + 1; % num words to play in this row
current_row_points = sum(B(start_index:stop_index,2)) - penalty*B(stop_index-1,1); % use length of next to last word to get number of penalty cols
if current_row_points > 0,
for cc = c:min(n,words_left+c-1),
wi = start_index-c+cc; % word index
board(r:(r+B(wi,1)-1),cc) = words{index(wi)};
isUnplayed2(index(wi)) = false;
end
% the row is unplayed I think it will simply be blank
end
c=1;
points = points + current_row_points;
r=r+B(stop_index,1)+1; % increment row location
k=k+1; % increment row number
start_index=stop_index+1;
stop_index = min(nwords, stop_index+n);
end
result = total - points;
wordlengths2 = wordlengths(isUnplayed);
weights2 = weights(isUnplayed);
[board,result] = james_sub_solver(board,wordlengths2,weights2,isUnplayed2,words,result,n);
end
function [sq, isUnplayed, hopeless] = press2(words, isUnplayed, hopeless, w2l, C1, alphaix,sq)
ii_valid = w2l(isUnplayed(w2l) & ~hopeless(w2l));
for ii = ii_valid, % w2l must be a row vector here
sq(1,:) = words{ii};
isUnplayed(ii) = false;
% only iterate over reasonable letters
conda = C1 == sq(1,1);
a1 = find(conda,1);
a2 = find(conda,1,'last');
w21jj = w2l(sort(alphaix(a1:a2)));
condb = C1 == sq(1,2);
b1=find(condb,1);
b2=find(condb,1,'last');
w21kk = w2l(sort(alphaix(b1:b2)));
for jj = w21jj
% eval order? also checks could be elim
if isUnplayed(jj) && ~hopeless(jj)
sq(2,1) = words{jj}(2);
isUnplayed(jj) = false;
condc = C1 == sq(2,1);
c1=find(condc,1);
c2=find(condc,1,'last');
w21ll = w2l(sort(alphaix(c1:c2)));
for kk = w21kk
if isUnplayed(kk)
sq(2,2) = words{kk}(2);
isUnplayed(kk) = false;
for ll = w21ll
if isUnplayed(ll) && all(sq(2,:) == words{ll})
isUnplayed(ll) = false;
return; % press completed!
end
end
isUnplayed(kk) = true;
end
end
isUnplayed(jj) = true;
end
end
isUnplayed(ii) = true;
% should mark words that didn't work out to avoid retrying them
hopeless(ii) = true; % hopeless in positions 1 or 2
end
sq = zeros(2);
end
function [board,result] = james_sub_solver(board,wordlengths,weights,isUnplayed,words,result,n)
wordlengths2 = wordlengths(isUnplayed);
weights2 = weights(isUnplayed);
words = words(isUnplayed);
[~,idx_sort] = sort(wordlengths2 - weights2/max(weights2) );
tres_ceros = board(3:end,1)==0 & board(2:end-1,2)==0 & board(1:end-2,1)==0;
r_ini = find(tres_ceros) + 1;
if board(n,1)==0 && board(n-1,1)==0
r_ini = [r_ini; n];
end
k = 1;
for p = 1:length(r_ini)
r = r_ini(p);
if board(r-1,1)==0
c = 1;
while c < n && board(r-1,c)==0
word_n = words{idx_sort(k)};
c2 = c + numel(word_n);
if c2-1 <= n && board(r-1,c2-1)==0
board(r,c:c2-1) = word_n;
k = k + 1;
result = result - weights2(idx_sort(k));
end
c = c2 + 1;
end
end
end
end
|