2011-04-20 12:00:00 UTC

# not worth

by Alex P.

Status: Passed
Results: 6934951 (cyc: 41, node: 5669)
CPU Time: 60.319
Score: 17375.0
Submitted at: 2011-04-16 09:09:12 UTC
Scored at: 2011-04-16 09:12:05 UTC

Current Rank: 864th (Highest: 1st )
Based on: KJ - minor chang not worth it (diff)
Basis for: thats not understandable (diff)
Basis for: Go to any length to win? (diff)

Code
```function board = solver(words, weights, N, penalty)

words = words(weights>0);
weights = weights(weights>0);
% Solvers by Nick, Victoria, Fel, Alfonso, James
nws     = numel(words);
lengths = zeros(1,nws);
B0 = zeros(N);

lengths=cellfun('length',words);
[BOARD{1}, SCORE(1)] = solver_nick(words, weights, N, penalty, lengths, nws, B0);
[BOARD{2}, SCORE(2)] = solver_fel(words, weights, N, penalty, lengths, nws);
[BOARD{3}, SCORE(3)] = solver_press(words, weights, N, penalty, lengths,B0);
[BOARD{4}, SCORE(4)] = solver_columns3(words, weights, N, penalty, lengths, nws);
[BOARD{5}, SCORE(5)] = solver_victoria(words, weights, N, penalty, lengths, nws);
[BOARD{6}, SCORE(6)] = solver_anieto(words, weights, N, penalty, lengths, nws,B0);

[~, board_idx]       = min(SCORE);
board                = BOARD{board_idx};
end

function [board, result] = solver_press(words, weights, n, penalty, wordlengths, board)
total = sum(weights);

[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(size(words));
hopeless = false(size(words));

[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,
[sq, isUnplayed, hopeless] = press2(words, isUnplayed, hopeless, w2l, C, alphaix);
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);

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),
%fprintf('\n* r=%2i,c=%2i\n',r,c);
wi = start_index-c+cc; % word index
%board(r:(r+B(wi,1)-1),cc)'
%char(words{index(wi)})
board(r:(r+B(wi,1)-1),cc) = words{index(wi)};
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;

end

% should mark words that didn't work out to avoid retrying them
% hopeless marks words that won't work i positions 1 or 2 (1 across and 1
% down). word 1 is equivalent to word 2, and word 3 is equivalent to word 4
% however, words 1 and 2 are not equivalent to words 3 and 4
function [sq, isUnplayed, hopeless] = press2(words, isUnplayed, hopeless, w2l, C, alphaix)
sq = zeros(2);

% try excluding words with letter frequencies of 1
% ordering words by first and second letter would help

for ii = w2l, % w2l must be a row vector here

%fprintf('ii = %i\n',ii);

if ~isUnplayed(ii) || hopeless(ii),
continue;
end

sq(1,:) = words{ii};
isUnplayed(ii) = false;

% fprintf('letter = %s\n',char(sq(1,:)));
% char(words{w2l(alphaix(a1:a2))})
% only iterate over reasonable letters
a1=find(C(:,1) == sq(1,1),1); a2=find(C(:,1) == sq(1,1),1,'last');

for jj = w2l(sort(alphaix(a1:a2))),
%fprintf('        jj = %i\n',ii,jj);
%assert(sq(1,1) == words{jj}(1));
if isUnplayed(jj) && ~hopeless(jj), % eval order? also checks could be elim
sq(2,1) = words{jj}(2);
isUnplayed(jj) = false;

b1=find(C(:,1) == sq(1,2),1); b2=find(C(:,1) == sq(1,2),1,'last');
c1=find(C(:,1) == sq(2,1),1); c2=find(C(:,1) == sq(2,1),1,'last');

for kk = w2l(sort(alphaix(b1:b2))),
%assert(sq(1,2) == words{kk}(1));
if isUnplayed(kk),
sq(2,2) = words{kk}(2);
isUnplayed(kk) = false;

for ll =  w2l(sort(alphaix(c1:c2))),
if isUnplayed(ll) && all(sq(2,:) == words{ll}),
isUnplayed(ll) = false;

%fprintf('1 %s\n2 %s\n3 %s\n4 %s\n\n',char(words{ii}),char(words{jj}),char(words{kk}),char(words{ll}));
%disp(char(sq))

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
%fprintf('%s (%i) is hopeless\n',char(words{ii}),ii);
end

sq=zeros(2); % no result

end

function [board, result] = solver_columns3(words, weights, n, penalty, wordlengths, nwords)
total = sum(weights);
board = zeros(n);

[B,index] = sortrows([wordlengths' weights'],[1 -2]);

points = 0;
k=1;
c=1;

current_stop_index = min(nwords, n*k); % check that we haven't run out of words

while (c+B(current_stop_index,1)-1) <= n,
current_col_points = sum(B(((k-1)*n)+1:current_stop_index,2)) - penalty*B(k*n-1,1); % use length of next to last word to get number of penalty cols
if current_col_points > 0,
words_left = current_stop_index - n*(k-1);
for r = 1:min(n,words_left),
board(c:(c+B(r+(k-1)*n,1)-1),r) = words{index(r+(k-1)*n)};
end
end
points = points + current_col_points;
c=c+B(current_stop_index,1)+1;

k=k+1;
current_stop_index = min(nwords, n*k);
end

result = total - points;

end

function [board, score] = solver_victoria(words, weights, N, penalty, L, QWords)

% Victoria's solver
score      = 0;
PThresh    = 0.19;
board      = zeros(N);

WordsInUse = false(1,QWords);

SpecificWeights = weights./(L + 1);
[~,IndWS]       = sort(SpecificWeights,'descend');
SpecLCum        = cumsum(L(IndWS) + 1);
MaxQ            = numel(find(SpecLCum <= N.*(N+1)));
GoodWeight      = sum(weights(IndWS(1:MaxQ)));

if P
slots   = ones(1,ceil(N/2));
MaxQ    = numel(find(SpecLCum <= (N+1).^2/2));
else
slots   = ones(1,N);
end

LoL         = min(L(IndWS(1:MaxQ)));
HiL         = max(L(IndWS(1:MaxQ)));
IndL        = zeros(MaxQ,1);
l           = 1;
for n = HiL:-1:LoL
idx_long       = find(L(IndWS(1:MaxQ))==n);
l2             = l + numel(idx_long);
IndL(l:l2-1)   = idx_long;
l              = l2;
end
IndWS(1:MaxQ) = IndWS(IndL);

n = 1;

while min(slots) < N && n <= QWords

Space = N - L(IndWS(n)) + 1 - slots;

SlotIndex = find(~Space,1);

if isempty(SlotIndex)
[Espacio,SlotIndex] = max(Space);
else
Espacio = 1;
end

if Espacio > 0
board((1+P)*SlotIndex-P,slots(SlotIndex):slots(SlotIndex) + L(IndWS(n)) - 1) = words{IndWS(n)};
slots(SlotIndex) = slots(SlotIndex) + L(IndWS(n)) + 1;

score = score + weights(IndWS(n));

WordsInUse(IndWS(n)) = true;
end

n=n+1;
end

if P
for n = 1:QWords

CurInd  = IndWS(n);
CurL    = L(CurInd);
word_c  = words{CurInd};

if ~WordsInUse(CurInd) && (CurL/2 ~= round(CurL/2))

[I,J] = find(board(1:N - CurL + 1,:) == word_c(1));

if ~isempty(I)

k = 1;

while ~WordsInUse(CurInd) && (k <= numel(I))

if all(word_c(1:2:end) == board(I(k):2:I(k) + CurL - 1,J(k))')

board(I(k):I(k) + CurL - 1,J(k)) = word_c';

score = score + weights(IndWS(n));

WordsInUse(IndWS(n)) = true;

end

k = k + 1;

end
end
end
end
end

pboard  = [board;zeros(1,N)];
cs      = cumsum(pboard(:)~=0);
ntrans  = sum(diff(cs(pboard==0))>1) + 1;
score   = sum(weights(:)) - score + penalty*ntrans;

end

function [board, score] = solver_nick(words, weights, N, penalty,wlen,nword,board)
% Nicks's solver
if min(wlen) == N

maxlen      = max(wlen);
pwords      = cellfun(@(a)[a 0 -1*ones(1,maxlen-numel(a))],words,'UniformOutput',false);
wmat        = cat(1,pwords{:});
wmat        = wmat(:,1:end-1);
m           = cell(N);

for n = 1:maxlen
m{n,1} = double(sparse(bsxfun(@eq,wmat(:,n),wmat(:,1)')));
m{3,n} = double(sparse(bsxfun(@eq,wmat(:,3),wmat(:,n)')));
end

rwords = zeros(1,N);
cwords = zeros(1,N);

n       = 1;
pm      = ones(nword);
m13     = m{n,1}*m{3,n};
ppm     = pm & m13;

while (n < N) && any(ppm(:))
pm = ppm;
n  = n + 2;
if (n < N)
m13 = m{n,1}*m{3,n};
ppm = pm & m13;
end
end

icross              = n;
open                = true(1,nword);
[i1,i3]             = find(pm);
i1                  = i1(1);
i3                  = i3(1);
open(i1)            = false;
open(i3)            = false;
board(1,1:wlen(i1)) = words{i1};
board(3,1:wlen(i3)) = words{i3};
rwords(1)           = i1;
rwords(3)           = i3;

for n = 1:2:icross

iword = find((m{n,1}(i1,:).*m{3,n}(:,i3)') & open);

if ~isempty(iword)
iword                   = iword(1);
cwords(n)               = iword;
board(1:wlen(iword),n)  = words{iword}';
open(iword)             = false;
end;
end;

% fill in remaining crosses, if possible.
fcwords     = cwords(cwords>0);
height      = max(wlen(fcwords));
open        = open';

for n = 5:height
cols            = find(board(n,:)~=0);
matches         = bsxfun(@eq,wmat(:,cols),board(n,cols))|(wmat(:,cols)<0);
[~,bm]          = max(open.*sum(matches,2));
end;

n = 5;
while (n <= height)
cols    = find(board(n,:)~=0);
row     = find(open & all(bsxfun(@eq,wmat(:,cols),board(n,cols))|(wmat(:,cols)<0),2),1);
if ~isempty(row)
open(row)               = false;
board(n,1:wlen(row))    = words{row};
rwords(n)               = row;
n                       = n+2;
else
n                       = n+1;
end;
end;
s0      = sum(weights(open));
board0  = board;

% now try full fill
openr   = rwords==0;
openc   = cwords==0;
goodc   = ~openc;

for c = find(openc)
rows            = find(board(:,c)~=0);
matches         = bsxfun(@eq,wmat(:,rows),board(rows,c)')|(wmat(:,rows)<0);
[~,bm]          = max(open.*sum(matches,2));
end

for c = find(openc)
rows        = find(board(:,c)~=0);
matches     = bsxfun(@eq,wmat(:,rows),board(rows,c)')|(wmat(:,rows)<0);
wi          = find(open & all(matches,2),1);
if ~isempty(wi)
open(wi)            = false;
board(1:wlen(wi),c) = words{wi};
cwords(c)           = wi;
end
end

openr = rwords==0;
openc = cwords==0;
goodr = ~openr;

for r = find(openr)
cols            = find(board(r,:)~=0);
matches         = bsxfun(@eq,wmat(:,cols),board(r,cols))|(wmat(:,cols)<0);
[~,bm]          = max(open.*sum(matches,2));
end;

for r = find(openr)
cols        = find(board(r,:)~=0);
matches     = bsxfun(@eq,wmat(:,cols),board(r,cols))|(wmat(:,cols)<0);
wi          = find(open & all(matches,2),1);
if ~isempty(wi)
open(wi)            = false;
board(r,1:wlen(wi)) = words{wi};
rwords(r)           = wi;
end;
end;

board(board==0) = 1;
s1              = sum(weights(open)) + penalty*(sum(rwords==0) + sum(cwords==0));
if s1 < s0
board0  = board;
s0      = s1;
end
else
board0  = zeros(N);
s0      = sum(weights);
end

%board   = zeros(N);
wcost   = weights./(wlen+1);
[~,r]   = sort(-wcost);
wlen    = wlen(r);
words   = words(r);
open    = true(1,numel(words));

w       = 0;
for n = [1:2:N,2:2:N]
l = 0;
k = find(open & (wlen<=N-l),1);
while ~isempty(k)
open(k)                = false;
word                   = words{k};
L_word                 = numel(word);
board(n,l+1:l+L_word)  = word;
l                      = l + L_word + 1;
w                      = w + weights(r(k));
k                      = find(open & (wlen <= N-l),1);
end
end

board2   = zeros(N);
w2       = 0;
open     = true(1,numel(words));
wlen_m_N = wlen <= N;

for n = 1:2:N
l = 0;
k = find(open & wlen_m_N,1);
while ~isempty(k)
open(k)                = false;
word                   = words{k};
L_word                 = numel(word);
board2(n,l+1:l+L_word) = word;
l                      = l+L_word+1;
w2                     = w2 + weights(r(k));
k                      = find(open & (wlen <= N-l),1);
end
end
pboard  = [board;zeros(1,N)];
cs      = cumsum(pboard(:)~=0);
ntrans  = sum(diff(cs(pboard==0))>1);

if penalty*ntrans > w-w2
board   = board2;
s       = sum(weights) - w2;
else
s       = sum(weights) - w+penalty*ntrans;
end

board2          = zeros(N);
w2              = 0;
open            = true(1,numel(words));
filled          = zeros(1,N);
filled(2:2:end) = 1;
brk             = false;
while (filled(1)<N)
wlen2           = wlen.*open;
wlen2(~open)    = 1;
nlen            = accumarray(wlen2(:),ones(nword,1));
k               = find(open & (wlen <= N-filled(1) -1) & (nlen(wlen)' >=N),1);
if isempty(k)
brk         = true;
break
end
targ                                 = wlen(k);
board2(1,filled(1)+1:filled(1)+targ) = words{k};
open(k)                              = false;
w2                                   = w2 + weights(r(k));
wlen_eq_targ                         = wlen==targ;
for n = 2:N
k                                    = find(open & wlen_eq_targ,1); % DFM SPEED
board2(n,filled(n)+1:filled(n)+targ) = words{k};
open(k)                              = false;
w2                                   = w2 + weights(r(k));
end
filled = filled + targ + 1;
end

if brk
% try two half-sets
brk = false;
while filled(1) < N
wlen2           = wlen.*open;
wlen2(~open)    = 1;
nlen            = accumarray(wlen2(:),ones(nword,1));
ldir            = 2*(filled(1) > filled(2)) - 1;
nlen(1)         = 0;
k               = find(open & (wlen <= N-filled(1) - 1) & (nlen(wlen)'>=ceil(N/2)) & (nlen(wlen+ldir)'>=ceil(N/2)),1);
if isempty(k)
brk         = true;
break
end
targ                                 = wlen(k);
board2(1,filled(1)+1:filled(1)+targ) = words{k};
open(k)                              = false;
w2                                   = w2 + weights(r(k));
for n = 2:N
idir                                      = ldir*(mod(n,2)==0);
k                                         = find(open&(wlen==targ+idir),1);
board2(n,filled(n)+1:filled(n)+targ+idir) = words{k};
open(k)                                   = false;
w2                                        = w2 + weights(r(k));
end;
filled = filled + targ + 1;
end
end

if brk
% try two half-sets off by 2
brk = false;
while filled(1) < N
wlen2           = wlen.*open;
wlen2(~open)    = 1;
nlen            = accumarray(wlen2(:),ones(nword,1));
nlen(1)         = 0;
nlen(end+2)     = 0;
k0              = find(open&(wlen<=N-filled(1)-2) & (nlen(wlen)'>=ceil(N/2)) & (nlen(wlen+2)'>=ceil(N/2)),1);
if isempty(k0)
brk = true;
break
end
if filled(1)>filled(2)
targ            = ones(1,N)*wlen(k0);
targ(2:2:end)   = wlen(k0)+2;
else
targ            = ones(1,N)*(wlen(k0)+2);
targ(2:2:end)   = wlen(k0);
end
for n = 1:N
k                                       = find(open&(wlen==targ(n)),1);
board2(n,filled(n)+1:filled(n)+targ(n)) = words{k};
open(k)                                 = false;
w2                                      = w2 + weights(r(k));
end;
filled = filled + targ + 1;
end
end
if brk && any(board2(:))
% finish filling board normally
for n = 1:N
k = find(open & (wlen<=N-filled(n)),1);
while ~isempty(k)
open(k)                                     = false;
word                                        = words{k};
board2(n,filled(n)+1:filled(n)+numel(word)) = word;
filled(n)                                   = filled(n) + numel(word) + 1;
w2                                          = w2 + weights(r(k));
k                                           = find(open & (wlen<=N-filled(n)),1);
end
end
end
pboard  = [board2; zeros(1,N)];
cs      = cumsum(pboard(:)~=0);
ntrans  = sum(diff(cs(pboard==0))>1);

s2      = sum(weights) + penalty*ntrans - w2;
if s2 < s
board   = board2;
s       = s2;
end

if (s0 < s)
board = board0;
s     = s0;
end

score = s;

end

function [board,score] = solver_anieto(words, weights, N, penalty, wordlength, nwords,board)

% Alfonso's solver
[wordlength,idxwords] = sort(wordlength);
idxpart               = [0, find(diff(wordlength)), nwords];
nwords_               = diff(idxpart);                          % number of words for each wordlength
lwords_               = wordlength(idxpart(2:end)); % list of wordlengths

n_                    = numel(lwords_);
words_                = cell(1,n_);
weights_              = words_;
weights0_             = words_;
for nword_= 1:n_,
idx1                = idxwords(idxpart(nword_)+1:idxpart(nword_+1));
[w,idx2]            = sort(weights(idx1),2,'descend');
weights0_{nword_}   = w;            % cumulative gains
words_{nword_}      = idx1(idx2);   % sorted words
weights_{nword_}    = cumsum(w);    % cumulative gains
end

borders = [1,1,N,N];

while size(borders,1)>0,
border = borders(1,:);
ntwn   = sum(prod(border(:,3:4),2),1);
Twn    = zeros(1,ntwn);
tn     = 0;
twn    = 0;
for nword_= find(nwords_>0),
t     = nwords_(nword_);
Twn(tn+(1:t)*lwords_(nword_)) = twn + weights0_{nword_};
tn                            = tn + t*lwords_(nword_);
if tn>=ntwn,
break;
end
end
Twn     = cumsum(Twn);

Cmax    = -inf;

for orientation=1:2,

r  = border(3);
c  = border(4);
rc = r*c;

for nword_ = find(nwords_>0&lwords_<=c),

m      = min(r,nwords_(nword_));
C      = weights_{nword_}(m) - penalty*lwords_(nword_) + E(rc-min(r,m+1)*(lwords_(nword_)+1),Twn);

if C(1)>0 && sum(C)>Cmax,
Imax = [orientation,1,nword_,m];
Cmax = sum(C);
end

m = min(ceil(r/2),nwords_(nword_));
C = weights_{nword_}(m) + E(rc-min(r,2*m)*(lwords_(nword_)+1),Twn);

if C(1)>0 && sum(C)>Cmax,
Imax = [orientation,2,nword_,m];
Cmax = sum(C);
end
end

border = border([2,1,4,3]);
end

if Cmax > 0

if Imax(1)==2,
board=board';
borders=borders(:,[2,1,4,3]);
end

border = borders(1,:);

switch(Imax(2))
case 1
nword_ = Imax(3);
m      = Imax(4);
for nw = 1:m,
board(border(1)+nw-1,border(2)+(0:lwords_(nword_)-1)) = words{words_{nword_}(nw)};
end
words_{nword_}      = words_{nword_}(m+1:end);
weights0_{nword_}   = weights0_{nword_}(m+1:end);
weights_{nword_}    = weights_{nword_}(m+1:end)-weights_{nword_}(m);
nwords_(nword_)     = nwords_(nword_)-m;
nwords              = nwords-m;
if m < border(3)-1,
borders(1,:)    = border + [0,lwords_(nword_)+1,m-border(3),-(lwords_(nword_)+1)];
borders         = cat(1,border+[m+1,0,-(m+1),0],borders);
else
borders(1,:)    = border + [0,lwords_(nword_)+1,0,-(lwords_(nword_)+1)];
end
case 2
nword_  = Imax(3);
m       = Imax(4);
for nw = 1:m,
board(border(1)+2*nw-2,border(2)+(0:lwords_(nword_)-1)) = words{words_{nword_}(nw)};
end
words_{nword_}      = words_{nword_}(m+1:end);
weights0_{nword_}   = weights0_{nword_}(m+1:end);
weights_{nword_}    = weights_{nword_}(m+1:end)-weights_{nword_}(m);
nwords_(nword_)     = nwords_(nword_)-m;
nwords              = nwords-m;
if 2*m-1<border(3)-1,
borders(1,:)    = border + [0,lwords_(nword_)+1,2*m-1-border(3),-(lwords_(nword_)+1)];
borders         = cat(1,border+[2*m,0,-2*m,0],borders);
else
borders(1,:)    = border + [0,lwords_(nword_)+1,0,-(lwords_(nword_)+1)];
end
case 3
end
if Imax(1)==2,
board   = board';
borders = borders(:,[2,1,4,3]);
end

borders(any(borders(:,3:4)<=0,2),:)=[];
else
borders(1,:)=[];
end

end

pboard  = [board;zeros(1,N)];
cs      = cumsum(pboard(:)~=0);
ntrans  = sum(diff(cs(pboard==0))>1);
score   = penalty*ntrans;

for N = 1:length(weights0_)
score = score + sum(weights0_{N});
end

end

function c=E(S,Twn)
if S>0
c=[0,Twn(ceil(S/2))];
else
c=[0,0];
end
end

function [board,score] = solver_fel(words, weights, N, penalty,Longitud,W)

idx_score_sorted = ordena_indices(weights,Longitud,1);

C  = ones(N,1)*(3*N);
if penalty == 0
dc = 1;
elseif sum(Longitud == N) >= N && (N-length(1:2:N))*weights(idx_score_sorted(ceil(N/2+1))) > N*penalty
dc = 1;
elseif (N-length(1:2:N))*mean(weights) > N*penalty
dc = 1;
else
dc = 2;
end
C(1:dc:N) = 0;

TIPOS      = 3;
SCORE = zeros(TIPOS,1);
for t = 1:TIPOS
SCORE(t)  = estimar_score(Longitud,weights,N,C,t);
end
[~, idx_better] = max(SCORE);
[board, score]  = colocar(words,Longitud,weights,penalty,N,W,C,idx_better);

% TIPOS      = 5;
% TRUE_SCORE = zeros(TIPOS,1);
% for t = 1:TIPOS
%     [BOARDS{t}, TRUE_SCORE(t)] = colocar(words,Longitud,weights,penalty,N,W,C,t);
% end
% [score, idx_true_better] = min(TRUE_SCORE);
% board = BOARDS{idx_true_better};

end

function score_est  = estimar_score(Longitud,weights,N,C,tipo)

idx_sorted      = ordena_indices(weights,Longitud,tipo);

idx_ultimo_est  = find(cumsum(Longitud(idx_sorted)+1) > sum(C==0)*N,1,'first');
score_est       = sum(weights(idx_sorted(1:idx_ultimo_est)));

end

function idx_sorted = ordena_indices(weights,Longitud,tipo)

switch tipo
case 1
[~,idx_sorted]          = sort(weights ,'descend');
case 2
mean_weights            = mean(weights(:));
idx_mas_de_media        = weights(:) > mean_weights;
[~,idx_sorted]          = sort(Longitud(:) - weights(:)/max(weights(:)) - (idx_mas_de_media)*10000,'ascend');
case 3
mean_weights            = mean(weights(:));
std_weights             = var(weights(:));
idx_mas_de_media_std    = weights(:) > mean_weights + 0.5*std_weights;
idx_menos_de_media      = weights(:) < mean_weights - 0.5*std_weights;
idx_penalties           = idx_mas_de_media_std - idx_menos_de_media;
[~,idx_sorted]          = sort(Longitud(:) - weights(:)/max(weights(:)) - (idx_penalties)*10000,'ascend');
case 4
mean_weights            = mean(weights(:));
std_weights             = var(weights(:));
idx_mas_de_media_std    = weights(:) > mean_weights + 0.6*std_weights;
idx_menos_de_media      = weights(:) < mean_weights - 0.6*std_weights;
idx_penalties           = idx_mas_de_media_std - idx_menos_de_media;
[~,idx_sorted]          = sort(Longitud(:) - weights(:)/max(weights(:)) - (idx_penalties)*10000,'ascend');
case 5
mean_weights            = mean(weights(:));
std_weights             = var(weights(:));
idx_mas_de_media_std    = weights(:) > mean_weights + 0.7*std_weights;
idx_menos_de_media      = weights(:) < mean_weights - 0.7*std_weights;
idx_penalties           = idx_mas_de_media_std - idx_menos_de_media;
[~,idx_sorted]          = sort(Longitud(:) - weights(:)/max(weights(:)) - (idx_penalties)*10000,'ascend');
end

end

function [board, score]  = colocar(words,Longitud,weights,penalty,N,W,C,tipo)

score       = 0;
SW          = sum(weights(:));
board       = zeros(N);
idx_sorted  = ordena_indices(weights,Longitud,tipo);

for m = 1:W

idx_wm = idx_sorted(m);
WORD   = words{idx_wm};
L      = Longitud(idx_wm);

N_max  = max(N-C);

if N_max < min(Longitud)
break
end

if L <= N_max

idx_f = find(C <= N - L,1,'first');

if isempty(idx_f)
weights(idx_wm)             = - weights(idx_wm);
else

score = score + weights(idx_wm);

idx_c                       = C(idx_f);
board(idx_f,idx_c + (1:L))  = WORD;
weights(idx_wm)             = 0;
Longitud(idx_wm)            = 100000;
C(idx_f)                    = C(idx_f)  + L + 1;

end

else
weights(idx_wm)                 = - weights(idx_wm);
end

end

pboard  = [board;zeros(1,N)];
cs      = cumsum(pboard(:)~=0);
ntrans  = sum(diff(cs(pboard==0))>1);
score   = SW - score + penalty*ntrans;

end
```