# Autogenerated with SMOP version 0.25.5-5-gef4bcde
# main.py fastsolver.m
from __future__ import division
from runtime import *
def solver_(A,B,w0,nargout=1):
    moves,optmove,optscore=cbest_(A,B,w0,nargout=3)
    curscore=sum_(w0[moves[:,1]])
    lots=1
    if length_(moves) - optmove < 20 or curscore / optscore < 1.05:
        lots=2
        return moves
    else:
        lenw=length_(w0)
        xx,nseq=sort_(rand_(1,lenw),nargout=2)
        A1=copy_(A)
        B1=copy_(B)
        w01=copy_(w0)
        for i in arange_(1,lenw).reshape(-1):
            A1[A == i]=nseq[i]
            B1[B == i]=nseq[i]
            w01[nseq[i]]=w0[i]
        moves2,optmove,optscore=cbest_(A1,B1,w01,nargout=3)
        moves22=copy_(moves2)
        for i in arange_(1,lenw).reshape(-1):
            moves22[moves2[:,1] == nseq[i],1]=i
        curscore2=sum_(w0[moves22[:,1]])
        if curscore2 < curscore:
            moves=copy_(moves22)
    n=length_(w0)
    ipos1=zeros_(n,1)
    ipos2=copy_(ipos1)
    fpos1=copy_(ipos1)
    fpos2=copy_(ipos1)
    for i in arange_(1,n).reshape(-1):
        ipos1[i],ipos2[i]=find_(A == i,nargout=2)
        fpos1[i],fpos2[i]=find_(B == i,nargout=2)
    optmove=sum_(abs_(fpos1 - ipos1) + abs_(fpos2 - ipos2))
    optscore=sum_((abs_(fpos1 - ipos1) + abs_(fpos2 - ipos2)).dot(w0))
    moves=improve_(A,B,w0,optmove,optscore,[ipos1,ipos2],[fpos1,fpos2],moves,lots)
    return moves
def cbest_(A,B,w0,nargout=1):
    lots=0
    n=length_(w0)
    ipos1=zeros_(n,1)
    ipos2=copy_(ipos1)
    fpos1=copy_(ipos1)
    fpos2=copy_(ipos1)
    for i in arange_(1,n).reshape(-1):
        ipos1[i],ipos2[i]=find_(A == i,nargout=2)
        fpos1[i],fpos2[i]=find_(B == i,nargout=2)
    optmove=sum_(abs_(fpos1 - ipos1) + abs_(fpos2 - ipos2))
    optscore=sum_((abs_(fpos1 - ipos1) + abs_(fpos2 - ipos2)).dot(w0))
    score=copy_(inf)
    if n != 28 or (numel_(A) / n) <= 1.98:
        mv=TLL79_(A,B,w0,optmove,optscore)
        movesTLL79=improve_(A,B,w0,optmove,optscore,[ipos1,ipos2],[fpos1,fpos2],mv,lots)
        scoreTLL79=sum_(w0[movesTLL79[:,1]])
        if (scoreTLL79 - optscore) > 0:
            movesA5=improve_(A,B,w0,optmove,optscore,[ipos1,ipos2],[fpos1,fpos2],itTakesAThief_(A,B,w0),lots)
            scoreA5=sum_(w0[movesA5[:,1]])
            if scoreTLL79 < scoreA5:
                moves=copy_(movesTLL79)
            else:
                moves=copy_(movesA5)
        else:
            moves=copy_(movesTLL79)
        flag=0
    else:
        flag=1
    if ((n >= 18 and n <= 20) or n == 28 or n == 23 or (n >= 13 and n <= 16)) and (flag or length_(moves) > 1.18 * optmove) and (numel_(A) / n) > 1.98:
        if ((score - optscore) < 20) or (not flag and (length_(moves) - optmove) < 2):
            return moves,optmove,optscore
        ym=size_(A,1)
        M=matlabarray([ym,1,- ym,- 1])
        mask=true_(1,n)
        w=abs_(w0[:].T) + 0.1
        rand_('seed',100)
        mov,ok=mainsolver_(A,B,w,mask,nargout=2)
        mov=1 * (mov == M[1]) + 2 * (mov == M[2]) + 3 * (mov == M[3]) + 4 * (mov == M[4])
        mov=matlabarray([(mov > 0) * (arange_(1,n)).T,sum_(mov,2)])
        mov=improve_(A,B,w0,optmove,optscore,[ipos1,ipos2],[fpos1,fpos2],mov,lots)
        if ok and flag == 0:
            if sum_(w0[mov[:,1]]) < sum_(w0[moves[:,1]]):
                moves=copy_(mov)
        else:
            moves=copy_(mov)
    return moves,optmove,optscore
def mainsolver_(A,B,w,mask,nargout=1):
    n=sum_(mask)
    if n == 0:
        ok=0
        return mov,ok
    mov,ok=easysolver_(A,B,w,mask,nargout=2)
    if ok:
        return mov,ok
    ipos=zeros_(size_(mask))
    for i in find_(mask).reshape(-1):
        ipos[i]=find_(A == i)
    invw=max_(w) + 1 - w
    blockers=sum_(findoverlaps_(cumsum_([[ipos],[mov]])))
    Apz=zeros_(size_(A))
    Bpz=zeros_(size_(B))
    for leaveout in arange_(ceil_(2 * log_(n)),(n - 1)).reshape(-1):
        mmask=copy_(mask)
        choosew=sum_(blockers).dot(invw)
        for i in arange_(1,leaveout).reshape(-1):
            small=find_(cumsum_(mmask.dot(choosew)) >= rand * sum_(mmask.dot(choosew)))
            mmask[small[1]]=false
        Ap=copy_(Apz)
        Bp=copy_(Bpz)
        for i in find_(mmask).reshape(-1):
            Ap[ipos[i]]=i
            Bp[B == i]=i
        partialmov,ok=mainsolver_(Ap,Bp,w + min_(w) * rand_(size_(w)),mmask,nargout=2)
        blockers=blockers + sum_(findoverlaps_(cumsum_([[ipos],[partialmov]])))
        if not ok:
            continue
        for i in find_(mask).reshape(-1):
            Ap[ipos[i]]=i
        for i in arange_(1,3 * sum_(mask)).reshape(-1):
            small=find_(cumsum_(w.dot((not mmask and mask))) >= rand * sum_(w.dot((not mmask and mask))))
            trymov,ok=imoves_(small[1],partialmov,Ap,B,mmask,nargout=2)
            if ok:
                mmask[small[1]]=true
                if isequal_(mmask,mask):
                    ok=1
                    mov=copy_(trymov)
                    return mov,ok
                partialmov=copy_(trymov)
            else:
                dropw=blockers.dot(invw)
                small=find_(cumsum_(dropw.dot((mmask and mask))) >= rand * sum_(dropw.dot((mmask and mask))))
                mmask[small[1]]=false
                partialmov[find_(partialmov[:,small[1]]),:]=[]
        ok=0
    return mov,ok
def imoves_(c,mov,A,B,mask,nargout=1):
    mov[find_(mov[:,c]),:]=[]
    nmov=size_(mov,1)
    crow,ccol=find_(A == c,nargout=2)
    trow,tcol=find_(B == c,nargout=2)
    if nmov == 0 and crow == trow and ccol == tcol:
        ok=1
        return mov,ok
    n=length_(mask)
    rows,cols=size_(A,nargout=2)
    slices=false_(rows,cols,nmov + 1)
    ipos=zeros_(1,n)
    for i in find_(mask).reshape(-1):
        ipos[i]=find_(A[:] == i)
    pos=cumsum_([[ipos],[mov]],1)
    for k in arange_(1,(nmov + 1)).reshape(-1):
        R=zeros_(size_(A))
        R[pos[k,mask]]=- 1
        slices[:,:,k]=(R == - 1)
    target=sub2ind_(size_(slices),trow,tcol,nmov + 1)
    optlen=abs_(crow - trow) + abs_(ccol - tcol)
    nnnn=numel_(slices)
    path=dijkstra_(nnnn,find_(A == c),target,slices,(1 + 0.1 * log_(nnnn)) * optlen)
    if isempty_(path):
        ok=0
        return mov,ok
    for i in arange_(length_(path),2,- 1).reshape(-1):
        if path[i] - path[i - 1] < rows * cols:
            k=floor_((path[i - 1] - 1) / (rows * cols)) + 1
            mov=matlabarray([[mov[1:(k - 1),:]],[zeros_(1,n)],[mov[k:mov.shape[0],:]]])
            mov[k,c]=path[i] - path[i - 1]
    ok=1
    return mov,ok
def easysolver_(A,B,w,mask,nargout=1):
    global TEST
    TEST=1
    NFIDDLE=5
    ok=0
    ym=size_(A,1)
    n=length_(mask)
    M=matlabarray([ym,1,- ym,- 1])
    moves=matlabarray([])
    ipos=zeros_(1,n)
    for i in find_(mask).reshape(-1):
        row,col=find_(A == i,nargout=2)
        rowt,colt=find_(B == i,nargout=2)
        nm=abs_(col - colt) + abs_(row - rowt)
        moves=matlabarray([[moves],[zeros_(nm,i - 1),[[M[1] * ones_(max_((colt - col),0),1)],[M[2] * ones_(max_((rowt - row),0),1)],[M[3] * ones_(max_((col - colt),0),1)],[M[4] * ones_(max_((row - rowt),0),1)]],zeros_(nm,n - i)]])
        ipos[i]=(col - 1) * ym + row
    nmov=size_(moves,1)
    if nmov == 0:
        ok=1
        return moves,ok
    moves=moves[randperm_(nmov),:]
    for i in arange_(1,NFIDDLE).reshape(-1):
        pos=cumsum_([[ipos],[moves]])
        okmov=min_(find_(any_(findoverlaps_(pos),2))) - 1
        if isempty_(okmov):
            ok=1
            return moves,ok
        indperm=localfiddler_(pos[okmov,:],moves[okmov:nmov,:],w)
        moves[okmov:nmov,:]=moves[okmov - 1 + indperm,:]
    pos=cumsum_([[ipos],[moves]])
    small=find_(any_(findoverlaps_(pos),2))
    okmov=small[1] - 1
    if isempty_(okmov):
        ok=1
        return moves,ok
    oldmoves=copy_(moves)
    for i in arange_(1,ceil_(sqrt_(nmov - okmov))).reshape(-1):
        pos=cumsum_([[ipos],[moves]])
        overlap=findoverlaps_(pos)
        if not any_(overlap[:]):
            ok=1
            return moves,ok
        else:
            small=find_(any_(overlap,2))
            oli=small[1]
            small=find_(overlap[oli,:])
            one=small[1]
            small=find_(overlap[oli,:])
            other=small[small.shape[0]]
            rowinds=matlabarray([oli - 1,min_(find_(moves[:,one] and (arange_(1,nmov)).T >= oli)),min_(find_(moves[:,other] and (arange_(1,nmov)).T >= oli)),max_(find_(moves[:,one] and (arange_(1,nmov)).T < oli - 1)),max_(find_(moves[:,other] and (arange_(1,nmov)).T < oli - 1))])
            indperm=localfiddler_(pos[oli - 1,:],moves[rowinds,:],w)
            moves[rowinds,:]=moves[rowinds[indperm],:]
    pos=cumsum_([[ipos],[moves]])
    small=find_(any_(findoverlaps_(pos),2))
    if isempty_(small) or (small[1] - 1 < okmov):
        moves=copy_(oldmoves)
    return moves,ok
def localfiddler_(ipos,mov,w,nargout=1):
    M=4
    nmov,n=size_(mov,nargout=2)
    if nmov <= M:
        M=copy_(nmov)
        P=perms_(arange_(1,M))
    else:
        M=min_(M,nmov)
        inds=arange_((M + 1),nmov)
        P=matlabarray([perms_(arange_(1,M)),inds[ones_(prod_(arange_(2,M)),1),:]])
        for i in arange_(1,size_(P,1)).reshape(-1):
            P[i,M + 1:nmov]=inds[randperm_(nmov - M)]
    f=zeros_(size_(P,1),1)
    for i in arange_(1,size_(P,1)).reshape(-1):
        newmov=mov[P[i,:],:]
        pos=cumsum_([[ipos],[newmov]])
        overlap=findoverlaps_(pos)
        if not any_(overlap[:]):
            indperm=P[i,:]
            return indperm
        else:
            p=any_(overlap,1)
            for c in arange_(1,n).reshape(-1):
                if p[c]:
                    small=find_(overlap[:,c])
                    f[i]=f[i] + w[c] * small[1]
                else:
                    f[i]=f[i] + w[c] * nmov
    DNC,best=max_(f,nargout=2)
    indperm=P[best,:]
    return indperm
def findoverlaps_(pos,nargout=1):
    npos,n=size_(pos,nargout=2)
    cols=find_(all_(pos))
    pos=pos[:,cols]
    A=zeros_(npos,length_(cols))
    sortpos,ind=sort_(pos,2,nargout=2)
    ind1=ind[:,1:ind.shape[1] - 1]
    ind2=ind[:,2:ind.shape[1]]
    dp=diff_(sortpos,1,2) == 0
    for i in arange_(1,npos).reshape(-1):
        A[i,ind1[i,dp[i,:]]]=true
        A[i,ind2[i,dp[i,:]]]=true
    overlaps=zeros_(npos,n)
    overlaps[:,cols]=A
    return overlaps
def dijkstra_(n,s,d,R,optlen,nargout=1):
    rows,cols,depth=size_(R,nargout=3)
    R=R[:]
    visited=false_(1,n)
    distance=inf * ones_(1,n)
    parent=zeros_(1,n)
    distance[s]=0
    stack=zeros_(1,n)
    stack[1]=s
    _next=1
    last=1
    for i in arange_(1,(n - 1)).reshape(-1):
        if _next > last:
            break
        else:
            u=stack[_next]
            _next=_next + 1
        visited[u]=true
        ndx=u - 1
        k=floor_(ndx / (rows * cols)) + 1
        ndx=rem_(ndx,rows * cols)
        col=floor_(ndx / rows) + 1
        ndx=rem_(ndx,rows)
        row=floor_(ndx) + 1
        v=u + 1
        if v > 0 and v <= n and not R[v] and row < rows:
            if distance[u] + 1 < distance[v]:
                distance[v]=distance[u] + 1
                parent[v]=u
                if not visited[v]:
                    if (v == d) and (distance[d] == optlen):
                        break
                    last=last + 1
                    stack[last]=v
        v=u - 1
        if v > 0 and v <= n and not R[v] and row > 1:
            if distance[u] + 1 < distance[v]:
                distance[v]=distance[u] + 1
                parent[v]=u
                if not visited[v]:
                    if (v == d) and (distance[d] == optlen):
                        break
                    last=last + 1
                    stack[last]=v
        v=u + rows
        if v > 0 and v <= n and not R[v] and col < cols:
            if distance[u] + 1 < distance[v]:
                distance[v]=distance[u] + 1
                parent[v]=u
                if not visited[v]:
                    if (v == d) and (distance[d] == optlen):
                        break
                    last=last + 1
                    stack[last]=v
        v=u - rows
        if v > 0 and v <= n and not R[v] and col > 1:
            if distance[u] + 1 < distance[v]:
                distance[v]=distance[u] + 1
                parent[v]=u
                if not visited[v]:
                    if (v == d) and (distance[d] == optlen):
                        break
                    last=last + 1
                    stack[last]=v
        v=u + rows * cols
        if v > 0 and v <= n and not R[v] and k < depth:
            if distance[u] < distance[v]:
                distance[v]=distance[u]
                parent[v]=u
                if not visited[v]:
                    if (v == d) and (distance[d] == optlen):
                        break
                    last=last + 1
                    stack[last]=v
    if parent[d] != 0:
        path=zeros_(1,distance[d] + depth)
        pathi=length_(path)
        t=copy_(d)
        path[pathi]=d
        pathi=pathi - 1
        while t != s:

            p=parent[t]
            path[pathi]=p
            pathi=pathi - 1
            t=copy_(p)

    else:
        path=matlabarray([])
    return path
def improve_(Ai,Af,w,optmove,optscore,Ci,Cf,mv,lots,nargout=1):
    dist=copy_(optscore)
    n_blk=length_(w)
    I=matlabarray([0,1,0,- 1])
    J=matlabarray([1,0,- 1,0])
    sc=sum_(w[mv[:,1]])
    mv_len=size_(mv,1)
    if sc == optscore:
        return mv
    if lots == 1:
        if ((sc - optscore) < 5) or ((mv_len - optmove) < 1):
            return mv
        num_fail=0
        max_try=min_(125,mv_len * 2)
        max_fail=copy_(max_try)
    else:
        if lots == 0:
            if ((sc - optscore) < 20) or ((mv_len - optmove) < 2):
                return mv
            num_fail=0
            max_try=min_(40,mv_len)
            max_fail=copy_(max_try)
        else:
            if lots == 2:
                if ((sc - optscore) < 5) or ((mv_len - optmove) < 1):
                    return mv
                num_fail=0
                max_try=min_(55,mv_len)
                max_fail=copy_(max_try)
    for j_try in arange_(1,max_try).reshape(-1):
        sc_old=copy_(sc)
        A=copy_(Ai)
        C=copy_(Ci)
        j=1
        while j < mv_len:

            if (mv[j,1] == mv[j + 1,1]) and (abs_(mv[j,2] - mv[j + 1,2]) == 2):
                sc=sc - 2 * w[mv[j,1]]
                mv=mv[[arange_(1,j - 1),arange_(j + 2,mv_len)],:]
                mv_len=mv_len - 2
                if sc == dist:
                    return mv
            else:
                if A[C[mv[j + 1,1],1] + I[mv[j + 1,2]],C[mv[j + 1,1],2] + J[mv[j + 1,2]]] == 0:
                    mv[[j,j + 1],:]=mv[[j + 1,j],:]
                else:
                    if j + 3 <= mv_len:
                        b=mv[j,1]
                        c=mv[j + 1,1]
                        d=mv[j + 2,1]
                        sit=0
                        if (b == mv[j + 3,1]) and (abs_(mv[j,2] - mv[j + 3,2]) == 2):
                            if (b == c) and (b == d) and (mv[j + 1,2] == mv[j + 2,2]):
                                b1=A[C[b,1] + I[mv[j + 1,2]],C[b,2] + J[mv[j + 1,2]]]
                                sit=1
                            else:
                                if (b == c) and (b != d) and (abs_(mv[j + 1,2] - mv[j + 2,2]) == 2):
                                    b1=copy_(d)
                                    sit=1
                                else:
                                    if (b != c) and (b == d) and (abs_(mv[j + 1,2] - mv[j + 2,2]) == 2):
                                        b1=copy_(c)
                                        sit=1
                                    else:
                                        if (b == c) and (b != d):
                                            sc=sc - 2 * w[b]
                                            mv[j,1]=d
                                            mv[j,2]=mv[j + 2,2]
                                            mv=mv[[arange_(1,j + 1),arange_(j + 4,mv_len)],:]
                                            mv_len=mv_len - 2
                        if sit == 1:
                            if w[b1] < w[b]:
                                mv[j,1]=b1
                                mv[j + 3,1]=b1
                                sc=sc - 2 * (w[b] - w[b1])
                if (sc - optscore) < 5:
                    return mv
                b=mv[j,1]
                r=C[b,1]
                c=C[b,2]
                nr=r + I[mv[j,2]]
                nc=c + J[mv[j,2]]
                A[r,c]=0
                A[nr,nc]=b
                C[b,1]=nr
                C[b,2]=nc
                j=j + 1

        if sc_old <= sc:
            num_fail=num_fail + 1
            if num_fail == max_fail:
                break
        else:
            num_fail=0
    return mv
def TLL79_(aInit,aFinal,wt,optmove,optscore,nargout=1):
    o=matlabarray([[3],[4],[1],[2]])
    move,score=solverA_(aInit,aFinal,wt,optmove,optscore,0,nargout=2)
    if ((score - optscore) > 20) or ((length_(move) - optmove) > 3):
        mv2,score2=solverA_(aFinal,aInit,wt,optmove,optscore,0,nargout=2)
        if score > score2:
            move=mv2[mv2.shape[0]:- 1:1,:]
            score=copy_(score2)
            move[:,2]=o[move[:,2]]
        if ((score - optscore) > 20) or ((length_(move) - optmove) > 3):
            a=copy_(aInit)
            midmoves=floor_(size_(move,1) / 2)
            I=matlabarray([0,1,0,- 1])
            J=matlabarray([1,0,- 1,0])
            for k in arange_(1,midmoves).reshape(-1):
                row,col=find_(a == move[k,1],nargout=2)
                a[row,col]=0
                row=row + I[move[k,2]]
                col=col + J[move[k,2]]
                a[row,col]=move[k,1]
            oldscore1=sum_(wt[move[1:midmoves,1]])
            oldscore2=sum_(wt[move[midmoves + 1:size_(move,1),1]])
            newmove,newscore=solverA_(aInit,a,wt,optmove,optscore,1,nargout=2)
            newmove2,newscore2=solverA_(a,aFinal,wt,optmove,optscore,1,nargout=2)
            newscore1=sum_(wt[newmove[:,1]])
            newscore2=sum_(wt[newmove2[:,1]])
            oldmove=copy_(move)
            if (newscore1 < oldscore1):
                move=copy_(newmove)
                if (newscore2 < oldscore2):
                    for itr in arange_(1,size_(newmove2,1)).reshape(-1):
                        move[move.shape[0] + 1,[1,2]]=[newmove2[itr,1],newmove2[itr,2]]
                else:
                    for itr in arange_(midmoves + 1,size_(oldmove,1)).reshape(-1):
                        move[move.shape[0] + 1,[1,2]]=[oldmove[itr,1],oldmove[itr,2]]
            else:
                if (newscore2 < oldscore2):
                    move=matlabarray([])
                    for itr in arange_(1,midmoves).reshape(-1):
                        move[move.shape[0] + 1,[1,2]]=[oldmove[itr,1],oldmove[itr,2]]
                    for itr in arange_(1,size_(newmove2,1)).reshape(-1):
                        move[move.shape[0] + 1,[1,2]]=[newmove2[itr,1],newmove2[itr,2]]
    return move
def solverA_(aInit,aFinal,wt,optmove,optscore,half,nargout=1):
    global Dperfect
    Dperfect=copy_(optmove)
    if half:
        optmove=1e+20
        optscore=1e+20
    move,isPerfect,score=solver2_(aInit,aFinal,wt,1111,optscore,nargout=3)
    if not isPerfect:
        move1=solver1_(aInit,aFinal,wt,score)
        if (not isempty_(move1)):
            isPerfect=length_(move1) == Dperfect
            score1=sum_(wt[move1[:,1]])
            if score1 < score:
                score=copy_(score1)
                move=copy_(move1)
    if isPerfect:
        score=0
    return move,score
def solver1_(aInit,aFinal,wt,bscore,nargout=1):
    COUNTERS=0
    allmoves=matlabarray([])
    wtinitori=copy_(wt)
    sortbydist=0
    sortbyweight=1
    minw=10000
    if sortbyweight:
        tmp,inds=sort_(- wt,nargout=2)
        wtinit=copy_(wtinitori)
    lenwt=length_(wt)
    absx=zeros_(lenwt,1)
    absy=copy_(absx)
    for index in arange_(1,lenwt).reshape(-1):
        hvix,hviy=find_(aInit == index,nargout=2)
        hvfx,hvfy=find_(aFinal == index,nargout=2)
        absx[index]=abs_(hvix - hvfx)
        absy[index]=abs_(hviy - hvfy)
    if sortbydist:
        dist=abs_(absx) + abs_(absy)
        tmp,inds=sort_(- dist,nargout=2)
        wtinit=copy_(wtinitori)
    for index in arange_(1,length_(inds)).reshape(-1):
        hv=inds[index]
        hvix,hviy=find_(aInit == hv,nargout=2)
        hvfx,hvfy=find_(aFinal == hv,nargout=2)
        dist=abs_(hvix - hvfx) + abs_(hviy - hvfy)
        wt[hv]=- Inf
        wtinit[hv]=wtinit[hv] + minw + 10000
        move,cost,aInit,COUNTERS=movefrompos_(hv,[hvix,hviy],[hvfx,hvfy],aInit,aFinal,wtinit,1,dist + 5,COUNTERS,nargout=4)
        if COUNTERS > 500:
            move=matlabarray([])
            return move
        if isinf_(cost) or isempty_(move):
            pass
        else:
            move=matlabarray([move[:,1],3 * abs_(move[:,4]) - move[:,4] + 2 * abs_(move[:,5]) - move[:,5]])
            allmoves=matlabarray([[allmoves],[move]])
            if (sum_(wtinitori[allmoves[:,1]]) > bscore):
                move=matlabarray([])
                return move
    count=1
    oldinds=matlabarray([])
    while not isequal_(aFinal,aInit):

        sortbyweight=copy_(sortbydist)
        sortbydist=not sortbyweight
        if sortbyweight:
            inds=find_(aFinal != aInit)
            inds=aFinal[inds]
            inds=inds[inds > 0]
            tmp,indices=sort_(- wt[inds],nargout=2)
            inds=inds[indices]
        if sortbydist:
            for index in arange_(1,length_(wt)).reshape(-1):
                hvix,hviy=find_(aInit == index,nargout=2)
                hvfx,hvfy=find_(aFinal == index,nargout=2)
                dist[index]=abs_(hvix - hvfx) + abs_(hviy - hvfy)
            tmp,inds=sort_(- dist,nargout=2)
            firstzeros=find_(tmp == 0)
            inds[firstzeros:inds.shape[0]]=[]
        wtinit=copy_(wtinitori)
        notmove=setdiff_(oldinds,inds)
        for hv in arange_(1,length_(notmove)).reshape(-1):
            wtinit[notmove[hv]]=wtinit[notmove[hv]] + minw + 10000
        for hind in arange_(1,length_(inds)).reshape(-1):
            hv=inds[hind]
            hvix,hviy=find_(aInit == hv,nargout=2)
            hvfx,hvfy=find_(aFinal == hv,nargout=2)
            dist=abs_(hvix - hvfx) + abs_(hviy - hvfy)
            wtinit[hv]=wtinit[hv] + minw + 10000
            move,cost,aInit,COUNTERS=movefrompos_(hv,[hvix,hviy],[hvfx,hvfy],aInit,aFinal,wtinit,1,dist + 6,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move
            if hind > 1:
                wtinit[inds[hind - 1]]=wtinit[inds[hind - 1]] - minw - 10000
            if isinf_(cost) or isempty_(move):
                pass
            else:
                move=matlabarray([move[:,1],3 * abs_(move[:,4]) - move[:,4] + 2 * abs_(move[:,5]) - move[:,5]])
                allmoves=matlabarray([[allmoves],[move]])
                if (sum_(wtinitori[allmoves[:,1]]) > bscore):
                    move=matlabarray([])
                    return move
        oldinds=copy_(inds)
        count=count + 1

    move=copy_(allmoves)
    return move
def movefrompos_(item,pinit,pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=1):
    COUNTERS=COUNTERS + 1
    cost=0
    curposnew=copy_(curpos)
    if isequal_(pinit,pfin):
        move=matlabarray([])
        return move,cost,curposnew,COUNTERS
    if recur == 0:
        move=matlabarray([])
        cost=0
        return move,cost,curposnew,COUNTERS
    diffx=pfin[1] - pinit[1]
    diffy=pfin[2] - pinit[2]
    dirx=sign_(diffx)
    diry=sign_(diffy)
    cost=copy_(Inf)
    if (strategy < 10 and abs_(diffx) > abs_(diffy)) or (strategy == 11 and abs_(diffx) < abs_(diffy)):
        if dirx and curpos[pinit[1] + dirx,pinit[2]] <= 0:
            move,cost,curposnew,COUNTERS=onemove_(item,pinit,[dirx,0],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if length_(move) > 0 and cost / size_(move,1) == mod_(wt[curpos[pinit[1],pinit[2]]],10000):
                return move,cost,curposnew,COUNTERS
        if diry and curpos[pinit[1],pinit[2] + diry] <= 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[0,diry],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if length_(move1) > 0 and cost1 / size_(move1,1) == mod_(wt[curpos[pinit[1],pinit[2]]],10000):
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
    else:
        if diry and curpos[pinit[1],pinit[2] + diry] <= 0:
            move,cost,curposnew,COUNTERS=onemove_(item,pinit,[0,diry],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if length_(move) > 0 and cost / size_(move,1) == mod_(wt[curpos[pinit[1],pinit[2]]],10000):
                return move,cost,curposnew,COUNTERS
        if dirx and curpos[pinit[1] + dirx,pinit[2]] <= 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[dirx,0],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if length_(move1) > 0 and cost1 / size_(move1,1) == mod_(wt[curpos[pinit[1],pinit[2]]],10000):
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
    if isinf_(cost) or cost == 0:
        if dirx and diry and curpos[pinit[1],pinit[2] + diry] > 0 and curpos[pinit[1] + dirx,pinit[2]] > 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[dirx,0],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[0,diry],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        else:
            if dirx and curpos[pinit[1] + dirx,pinit[2]] > 0:
                move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[dirx,0],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
                if COUNTERS > 500:
                    move=matlabarray([])
                    return move,cost,curposnew,COUNTERS
                if cost1 < cost:
                    move=copy_(move1)
                    cost=copy_(cost1)
                    curposnew=copy_(curposnew1)
            if diry and curpos[pinit[1],pinit[2] + diry] > 0:
                move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,[0,diry],pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=4)
                if COUNTERS > 500:
                    move=matlabarray([])
                    return move,cost,curposnew,COUNTERS
                if cost1 < cost:
                    move=copy_(move1)
                    cost=copy_(cost1)
                    curposnew=copy_(curposnew1)
    if isinf_(cost) and recur > 1 and abs_(strategy) < 5:
        mv=matlabarray([dirx,diry])
        mv1=abs_(mv) - 1
        if any_(mv1):
            mv2=abs_(mv1)
            mv3=- mv
            ok3=1
        else:
            mv1=matlabarray([- mv[1],0])
            mv2=matlabarray([0,- mv[2]])
            ok3=0
        sz=size_(curpos)
        strategy=strategy + sign_(strategy) * 1
        if all_(pinit + mv1 > 0) and all_(pinit + mv1 <= sz) and not curpos[pinit[1] + mv1[1],pinit[2] + mv1[2]]:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv1,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        if all_(pinit + mv2 > 0) and all_(pinit + mv2 <= sz) and not curpos[pinit[1] + mv2[1],pinit[2] + mv2[2]]:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv2,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        if ok3 and all_(pinit + mv3 > 0) and all_(pinit + mv3 <= sz) and not curpos[pinit[1] + mv3[1],pinit[2] + mv3[2]]:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv3,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        if all_(pinit + mv1 > 0) and all_(pinit + mv1 <= sz) and curpos[pinit[1] + mv1[1],pinit[2] + mv1[2]] > 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv1,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        if all_(pinit + mv2 > 0) and all_(pinit + mv2 <= sz) and curpos[pinit[1] + mv2[1],pinit[2] + mv2[2]] > 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv2,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
        if ok3 and all_(pinit + mv3 > 0) and all_(pinit + mv3 <= sz) and curpos[pinit[1] + mv3[1],pinit[2] + mv3[2]] > 0:
            move1,cost1,curposnew1,COUNTERS=onemove_(item,pinit,mv3,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
            if COUNTERS > 500:
                move=matlabarray([])
                return move,cost,curposnew,COUNTERS
            if cost1 < cost:
                move=copy_(move1)
                cost=copy_(cost1)
                curposnew=copy_(curposnew1)
    if isinf_(cost):
        move=matlabarray([])
        curposnew=copy_(curpos)
    return move,cost,curposnew,COUNTERS
def onemove_(item,pinit,movedir,pfin,curpos,finpos,wt,strategy,recur,COUNTERS,nargout=1):
    COUNTERS=COUNTERS + 1
    move3=0
    curcost=mod_(wt[curpos[pinit[1],pinit[2]]],10000)
    costnew3=0
    newpos=pinit + movedir
    if curpos[newpos[1],newpos[2]] > 0:
        if wt[curpos[newpos[1],newpos[2]]] > 8000:
            cost=copy_(Inf)
            move=matlabarray([])
            return move,cost,curpos,COUNTERS
        if wt[curpos[newpos[1],newpos[2]]] > 2 * curcost and recur > 0 and strategy > 0:
            tmppos1=abs_(movedir) - 1 + pinit
            tmppos2=abs_(movedir) - 1 + pinit
            tmppos3=movedir + tmppos1
            tmppos4=movedir + tmppos2
            sz=size_(curpos)
            wt2=matlabarray([[0],[wt]])
            curpos2=copy_(curpos)
            curpos2[curpos2 < 0]=0
            curpos2=curpos2 + 1
            tmpcost=matlabarray([Inf,Inf])
            if all_(tmppos1 > 0) and all_(tmppos1 <= sz):
                if all_(tmppos3 > 0) and all_(tmppos3 <= sz):
                    tmpcost[1]=wt2[curpos2[tmppos1[1],tmppos1[2]]] + wt2[curpos2[tmppos1[1],tmppos1[2]]] + 2 * curcost
            tmpcost[2]=tmpcost[1]
            if tmpcost[2] < wt[curpos[newpos[1],newpos[2]]]:
                move3,costnew3,curpostmp,COUNTERS=onemove_(item,pinit,tmppos2 - pinit,pfin,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                if not isinf_(costnew3):
                    move4,costnew4,curpostmp,COUNTERS=onemove_(item,tmppos2,tmppos4 - tmppos2,pfin,curpostmp,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                    if not isinf_(costnew4):
                        move5,costnew5,curpostmp,COUNTERS=movefrompos_(item,tmppos4,pfin,curpostmp,finpos,wt,- strategy,recur - 1,COUNTERS,nargout=4)
                        cost=costnew3 + costnew4 + costnew5
                        move=matlabarray([[move3],[move4],[move5]])
                        if not isinf_(cost):
                            curpos=copy_(curpostmp)
                        return move,cost,curpos,COUNTERS
        newitem=curpos[newpos[1],newpos[2]]
        pfin2=matlabarray([])
        pfin2[1],pfin2[2]=find_(finpos == newitem,nargout=2)
        dirx2=sign_(pfin2[1] - newpos[1])
        diry2=sign_(pfin2[2] - newpos[2])
        wt[newitem]=wt[newitem] + 20000
        if isequal_([dirx2,diry2],- movedir) or isequal_(newpos,pfin2):
            costnew3=copy_(Inf)
        else:
            move3,costnew3,curposnew,COUNTERS=movefrompos_(newitem,newpos,pfin2,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
            if costnew3 == 0:
                costnew3=copy_(Inf)
            if not isinf_(costnew3):
                curpos=copy_(curposnew)
        if isinf_(costnew3):
            wtdir=matlabarray([Inf,Inf,Inf,Inf])
            diffpos=pfin - newpos
            if (diffpos[1] and movedir[1]) or (diffpos[2] and movedir[2]):
                mv1=abs_(movedir) - 1
            else:
                if any_(sign_(diffpos) > 0):
                    mv1=abs_(movedir) - 1
                else:
                    mv1=abs_(abs_(movedir) - 1)
            mv2=- mv1
            mv3=copy_(movedir)
            sz=size_(curpos)
            if all_(newpos + mv1 > 0) and all_(newpos + mv1 <= sz):
                if curpos[newpos[1] + mv1[1],newpos[2] + mv1[2]] <= 0:
                    move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv1,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                else:
                    wtdir[1]=wt[curpos[newpos[1] + mv1[1],newpos[2] + mv1[2]]]
            if isinf_(costnew3) and all_(newpos + mv2 > 0) and all_(newpos + mv2 <= sz):
                if curpos[newpos[1] + mv2[1],newpos[2] + mv2[2]] <= 0:
                    move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv2,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                else:
                    wtdir[2]=wt[curpos[newpos[1] + mv2[1],newpos[2] + mv2[2]]]
            if isinf_(costnew3) and all_(newpos + mv3 > 0) and all_(newpos + mv3 <= sz):
                if curpos[newpos[1] + mv3[1],newpos[2] + mv3[2]] <= 0:
                    move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv3,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                else:
                    wtdir[3]=wt[curpos[newpos[1] + mv3[1],newpos[2] + mv3[2]]]
            if isinf_(costnew3):
                wtdir,si=sort_(wtdir,nargout=2)
                for index in arange_(1,length_(wtdir)).reshape(-1):
                    if not isinf_(wtdir[index]) and isinf_(costnew3):
                        if 1 == si[index]:
                            move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv1,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                        else:
                            if 2 == si[index]:
                                move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv2,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
                            else:
                                if 3 == si[index]:
                                    move3,costnew3,curpos,COUNTERS=movefrompos_(newitem,newpos,newpos + mv3,curpos,finpos,wt,strategy,- 1,COUNTERS,nargout=4)
        wt[newitem]=wt[newitem] - 20000
        if isinf_(costnew3) or costnew3 == 0:
            cost=copy_(Inf)
            move=matlabarray([])
            return move,cost,curpos,COUNTERS
    if curpos[newpos[1],newpos[2]] == - item:
        cost=copy_(Inf)
        move=matlabarray([])
        return move,cost,curpos,COUNTERS
    curpos[newpos[1],newpos[2]]=curpos[pinit[1],pinit[2]]
    curpos[pinit[1],pinit[2]]=- curpos[pinit[1],pinit[2]]
    if recur > 0:
        move2,costnew,curposnew,COUNTERS=movefrompos_(item,pinit + movedir,pfin,curpos,finpos,wt,strategy,recur - 1,COUNTERS,nargout=4)
    else:
        move2,costnew,curposnew,COUNTERS=movefrompos_(item,pinit + movedir,pfin,curpos,finpos,wt,strategy,0,COUNTERS,nargout=4)
    curpos=copy_(curposnew)
    if curpos[pinit[1],pinit[2]] < 0:
        curpos[pinit[1],pinit[2]]=0
    if numel_(move3) == 1 and isempty_(move2):
        move=matlabarray([item,pinit,movedir])
    else:
        if numel_(move3) == 1:
            move=matlabarray([[item,pinit,movedir],[move2]])
        else:
            if isempty_(move2):
                move=matlabarray([[move3],[item,pinit,movedir]])
            else:
                move=matlabarray([[move3],[item,pinit,movedir],[move2]])
    cost=costnew3 + costnew + curcost
    return move,cost,curpos,COUNTERS
def solver2_(ai,af,w,states,optscore,nargout=1):
    global Ac,Ar,m2,Dperfect
    perfectMV=copy_(false)
    nBlocks=length_(w)
    m,n=size_(ai,nargout=2)
    m2=m + 2
    n2=n + 2
    A=- ones_(m2,n2)
    Af=copy_(A)
    A[2:m + 1,2:n + 1]=ai
    Af[2:m + 1,2:n + 1]=af
    Ac=arange_(1,n2)
    Ac=Ac[ones_(m2,1),:]
    Ar=(arange_(1,m2)).T
    Ar=Ar[:,ones_(n2,1)]
    Pi=copy_(w)
    Pf=copy_(w)
    for i in arange_(m2 + 2,numel_(A) - m2 - 1).reshape(-1):
        if A[i] > 0:
            Pi[A[i]]=i
        if Af[i] > 0:
            Pf[Af[i]]=i
    P=copy_(Pi)
    nmv=1
    mv=zeros_(300,2)
    nNOK=sum_(P != Pf)
    Paths=zeros_(m + n,nBlocks)
    lPaths=copy_(w)
    fPaths=copy_(w)
    Pend=copy_(w)
    bOK=copy_(w)
    obs=zeros_(nBlocks,2)
    nmv0=0
    while nmv0 < nmv and nNOK:

        obs[:]=0
        nmv0=copy_(nmv)
        for i in arange_(1,nBlocks).reshape(-1):
            if P[i] == Pf[i]:
                lPaths[i]=0
                fPaths[i]=0
                bOK[i]=1
            else:
                P1,f1=SearchPath_(A,P[i],Pf[i],nargout=2)
                if isempty_(P1):
                    lPaths[i]=0
                    fPaths[i]=0
                    obs[i,1:length_(f1)]=f1
                else:
                    if isempty_(f1):
                        fPaths[i]=1
                    else:
                        fPaths[i]=0
                        obs[i,1:length_(f1)]=f1
                    lPaths[i]=length_(P1)
                    Paths[1:lPaths[i],i]=P1.T
                    Pend[i]=P1[P1.shape[0]]
                bOK[i]=0
        iP=find_(not bOK and lPaths)
        PCol=zeros_(length_(iP))
        L=lPaths[iP]
        for i in arange_(1,length_(iP)).reshape(-1):
            Pe=Pend[iP[i]]
            for j in arange_(1,length_(iP)).reshape(-1):
                if i != j:
                    lj=L[j]
                    PCol[i,j]=any_(Paths[1:lj,iP[j]] == Pe)
        sPCol=sum_(PCol,2)
        pOK=find_(sPCol == 0)
        pNOK=find_(sPCol != 0)
        if isempty_(pOK):
            if length_(pNOK) == 1:
                pOK[pOK.shape[0] + 1]=pNOK
            else:
                if not isempty_(pNOK):
                    if length_(pNOK) > 1 and any_(fPaths[iP[pNOK]]):
                        pNOK[not fPaths[iP[pNOK]]]=[]
                    iNOK1=pNOK[find_(sPCol[pNOK] == 1)]
                    for i in iNOK1.T.reshape(-1):
                        j=find_(PCol[i,:])
                        jj=iP[j]
                        p=iP[i]
                        pe=Pend[p]
                        A[P[p]]=0
                        A[pe]=p
                        P1,f1=SearchPath_(A,P[jj],Pf[jj],nargout=2)
                        A[P[p]]=p
                        A[pe]=0
                        if isempty_(f1):
                            pOK[pOK.shape[0] + 1]=i
                            break
        if length_(pOK) > 1:
            obs1=abs_(obs[:])
            temp=zeros_(1,length_(obs1))
            i=1
            q=0
            pOK1=copy_(pOK)
            while i <= length_(obs1):

                temp[obs1 == obs1[i]]=1
                if sum_(temp) > 1:
                    j=find_(obs1 == obs1[i])
                    obs1[j[2:obs1.shape[0]]]=[]
                if any_(obs1[i] == pOK):
                    q=1
                    j=find_(obs1[i] == pOK)
                    pOK1[j]=0
                i=i + 1

            if q:
                pOK[pOK1 != 0]=[]
            if length_(pOK) > 1 and any_(fPaths[iP[pOK]]):
                pOK[not fPaths[iP[pOK]]]=[]
        j=1
        while j <= length_(pOK):

            i=pOK[j]
            b=iP[i]
            k=arange_(nmv + 1,nmv + L[i])
            mv[k,1]=b
            mv[k,2]=Paths[1:L[i],b]
            nmv=nmv + L[i]
            A[P[b]]=0
            A[Pend[b]]=b
            P[b]=Pend[b]
            if fPaths[b]:
                nNOK=nNOK - 1
            j=j + 1


    P=copy_(Pi)
    for i in arange_(2,nmv).reshape(-1):
        b=mv[i]
        p=mv[i,2]
        dp=p - P[b]
        if dp == 1:
            mv[i,2]=2
        else:
            if dp == - 1:
                mv[i,2]=4
            else:
                if dp == m2:
                    mv[i,2]=1
                else:
                    mv[i,2]=3
        P[b]=p
    mv=mv[2:nmv,:]
    if nNOK:
        rand_('state',states)
        mv2=matlabarray([[mv],[Faster10IntReps2_(A[2:m + 1,2:n + 1],af,w)]])
        score=sum_(w[mv2[:,1]])
        if abs_(score - optscore) < 5:
            perfectMV=(Dperfect == size_(mv2,1))
            mv=copy_(mv2)
            return mv,perfectMV,score
        if abs_(score - optscore) > 9000:
            perfectMV=(Dperfect == size_(mv2,1))
            mv=copy_(mv2)
            return mv,perfectMV,score
        rand_('state',states * 2)
        mv1=matlabarray([[mv],[Faster10IntReps2_(A[2:m + 1,2:n + 1],af,w)]])
        score1=sum_(w[mv1[:,1]])
        if score1 == score:
            mv=copy_(mv2)
            score=copy_(score1)
        else:
            if score1 < score:
                mv2=copy_(mv1)
                score=copy_(score1)
            if abs_(score - optscore) < 15:
                perfectMV=(Dperfect == size_(mv2,1))
                mv=copy_(mv2)
                return mv,perfectMV,score
            rand_('state',states * 371)
            mv1=matlabarray([[mv],[Faster10IntReps2_(A[2:m + 1,2:n + 1],af,w)]])
            score1=sum_(w[mv1[:,1]])
            if score1 == score:
                mv=copy_(mv2)
                perfectMV=Dperfect == size_(mv,1)
                return mv,perfectMV,score
            if score1 < score:
                mv2=copy_(mv1)
                score=copy_(score1)
            if abs_(score - optscore) < 500:
                perfectMV=(Dperfect == size_(mv2,1))
                mv=copy_(mv2)
                return mv,perfectMV,score
            rand_('state',states * 173)
            mv1=matlabarray([[mv],[Faster10IntReps2_(A[2:m + 1,2:n + 1],af,w)]])
            score1=sum_(w[mv1[:,1]])
            if score1 < score:
                mv2=copy_(mv1)
                score=copy_(score1)
            mv=copy_(mv2)
        perfectMV=Dperfect == size_(mv,1)
    else:
        score=sum_(w[mv[:,1]])
        perfectMV=1
    return mv,perfectMV,score
def SearchPath_(A,p1,p2,nargout=1):
    global Ac,Ar,m2
    c1=Ac[p1]
    c2=Ac[p2]
    r1=Ar[p1]
    r2=Ar[p2]
    stopped=matlabarray([])
    P=matlabarray([])
    if r1 > r2:
        d_r=- 1
    else:
        if r1 < r2:
            d_r=1
        else:
            d_r=0
    if c1 > c2:
        d_c=- 1
    else:
        if c1 < c2:
            d_c=1
        else:
            d_c=0
    n=0
    p=copy_(p1)
    if d_r == 0 or d_c == 0:
        while p != p2:

            np=p + d_c * m2 + d_r
            if A[np]:
                stopped=A[np]
                break
            p=copy_(np)
            n=n + 1
            P[n]=p

    else:
        Ah=copy_(A)
        c=copy_(c2)
        i1=p2 - d_r
        r_1=r2 - d_r
        while c != c1:

            r=copy_(r_1)
            r_1=0
            i2=copy_(i1)
            while r != r1:

                if Ah[i2]:
                    Afil=- Ah[i2]
                    if r == r2:
                        r_1=copy_(r2)
                        i1=i2 - d_c * m2
                    else:
                        r_1=r + d_r
                        i1=i2 - d_c * m2 + d_r
                    r=r - d_r
                    i2=i2 - d_r
                    while r != r1:

                        if Ah[i2] == 0:
                            Ah[i2]=Afil
                        r=r - d_r
                        i2=i2 - d_r

                    if Ah[i2] == 0:
                        Ah[i2]=Afil
                    break
                r=r - d_r
                i2=i2 - d_r

            if r_1 == 0 and Ah[i2]:
                i1=i2 - d_c * m2 + d_r
                r_1=r + d_r
            c=c - d_c
            if r_1 == 0:
                break

        r=copy_(r2)
        i1=p2 - d_c * m2
        c_1=c2 - d_c
        while r != r1:

            c=copy_(c_1)
            c_1=0
            i2=copy_(i1)
            while c != c1:

                if Ah[i2]:
                    if Ah[i2] < 0:
                        Afil=Ah[i2]
                    else:
                        Afil=- Ah[i2]
                    if c == c2:
                        c_1=copy_(c2)
                        i1=i2 - d_r
                    else:
                        c_1=c + d_c
                        i1=i2 - d_r + d_c * m2
                    c=c - d_c
                    i2=i2 - d_c * m2
                    while c != c1:

                        if Ah[i2] == 0:
                            Ah[i2]=Afil
                        c=c - d_c
                        i2=i2 - d_c * m2

                    if Ah[i2] == 0:
                        Ah[i2]=Afil
                    break
                c=c - d_c
                i2=i2 - d_c * m2

            if c_1 == 0 and Ah[i2]:
                i1=i2 - d_r + d_c * m2
                c_1=c + d_c
            r=r - d_r
            if c_1 == 0:
                break

        while p != p2:

            if c1 != c2 and Ah[p + m2 * d_c] == 0:
                di=m2 * d_c
                dc=copy_(d_c)
                dr=0
            else:
                if r1 != r2 and Ah[p + d_r] == 0:
                    di=copy_(d_r)
                    dc=0
                    dr=copy_(d_r)
                else:
                    if c1 == c2:
                        stopped=Ah[p + d_r]
                    else:
                        if r1 == r2:
                            stopped=Ah[p + m2 * d_c]
                        else:
                            stopped=matlabarray([Ah[p + d_r],Ah[p + m2 * d_c]])
                    break
            p=p + di
            n=n + 1
            P[n]=p
            r1=r1 + dr
            c1=c1 + dc

    return P,stopped
def Faster10IntReps2_(init,final,wts,nargout=1):
    global Dperfect
    numtimes=8
    if (max_(size_(init)) > 30) and max_(size_(wts)) / (size_(init,1) * size_(init,2)) > 0.25:
        numtimes=10
    else:
        if (max_(size_(init)) > 30):
            numtimes=7
        else:
            if (max_(size_(init)) < 11):
                numtimes=2
    bscore=1e+20
    for repcount in arange_(1,numtimes).reshape(-1):
        movelist,c=matrixsolver_(init,final,wts,nargout=2)
        bf=length_(wts) + 1 + zeros_(size_(init) + 2)
        bf[2:bf.shape[0] - 1,2:bf.shape[1] - 1]=final
        tries=1
        maxtries=15
        while not isequal_(c,bf) and (tries < maxtries):

            randwts=rand_(size_(wts))
            addtomovelist,c=matrixsolver_(c[2:c.shape[0] - 1,2:c.shape[1] - 1],final,randwts,nargout=2)
            movelist=matlabarray([[movelist],[addtomovelist]])
            tries=tries + 1

        if not isequal_(c,bf):
            movegoaltries=0
            while not isequal_(c,bf) and (movegoaltries < 20):

                problemboxes=c[c != bf and c != 0]
                openspots=find_(c == 0)
                tempfinal=copy_(bf)
                for i in arange_(1,length_(problemboxes)).reshape(-1):
                    cgind=find_(bf == problemboxes[i])
                    tempfinal[cgind]=0
                    newind=ceil_(rand * length_(openspots))
                    tempfinal[openspots[newind]]=problemboxes[i]
                    openspots[newind]=[]
                randwts=rand_(size_(wts))
                addtomovelist,c=matrixsolver_(c[2:c.shape[0] - 1,2:c.shape[1] - 1],tempfinal[2:tempfinal.shape[0] - 1,2:tempfinal.shape[1] - 1],randwts,nargout=2)
                movelist=matlabarray([[movelist],[addtomovelist]])
                movegoaltries=movegoaltries + 1
                aftermovegoaltries=0
                while not isequal_(c,bf) and aftermovegoaltries < 5:

                    randwts=rand_(size_(wts))
                    addtomovelist,c=matrixsolver_(c[2:c.shape[0] - 1,2:c.shape[1] - 1],final,randwts,nargout=2)
                    movelist=matlabarray([[movelist],[addtomovelist]])
                    aftermovegoaltries=aftermovegoaltries + 1


        score=sum_(wts[movelist[:,1]])
        if score < bscore:
            bmovelist=copy_(movelist)
            if length_(bmovelist) == Dperfect:
                return bmovelist
            bscore=copy_(score)
    return bmovelist
def matrixsolver_(init,final,wts,nargout=1):
    biggermatrix=length_(wts) + 1 + zeros_(size_(init) + 2)
    bi=copy_(biggermatrix)
    bf=copy_(bi)
    bi[2:bi.shape[0] - 1,2:bi.shape[1] - 1]=init
    bf[2:bf.shape[0] - 1,2:bf.shape[1] - 1]=final
    c=copy_(bi)
    m,n=size_(c,nargout=2)
    numboxes=length_(wts)
    DNC,wtorder=sort_(wts,nargout=2)
    movelist=zeros_(0,2)
    for i in arange_(1,numboxes).reshape(-1):
        cbn=wtorder[i]
        cr=0
        cc=0
        fr=0
        fc=0
        for j in arange_(2,m - 1).reshape(-1):
            for k in arange_(2,n - 1).reshape(-1):
                if c[j,k] == cbn:
                    cr=copy_(j)
                    cc=copy_(k)
                    if fr > 0:
                        break
                if bf[j,k] == cbn:
                    fr=copy_(j)
                    fc=copy_(k)
                    if cr > 0:
                        break
            if fr > 0 and cr > 0:
                break
        dr=fr - cr
        dc=fc - cc
        while dr != 0 or dc != 0:

            neighborhood=matlabarray([c[cr,cc + 1],c[cr + 1,cc],c[cr,cc - 1],c[cr - 1,cc]])
            opendirs=find_(not neighborhood)
            desireddirs=matlabarray([])
            if dr != 0:
                desireddirs[desireddirs.shape[0] + 1]=- sign_(dr) + 3
            if dc != 0:
                desireddirs[desireddirs.shape[0] + 1]=- sign_(dc) + 2
            pic=opendirs[ismember1_(opendirs,desireddirs)]
            if not isempty_(pic):
                if length_(pic) > 1:
                    if abs_(dr) > abs_(dc):
                        movedir=desireddirs[1]
                    else:
                        movedir=desireddirs[2]
                else:
                    movedir=copy_(pic)
            else:
                ind=ceil_(rand * length_(desireddirs))
                boxtomove=neighborhood[desireddirs[ind]]
                if [1,3] == desireddirs[ind]:
                    rcaxis=- 1
                else:
                    if [2,4] == desireddirs[ind]:
                        rcaxis=1
                c,movelist,rejectflag=outoftheway_(boxtomove,rcaxis,cbn,c,movelist,bf,nargout=3)
                ootwtries=1
                while rejectflag and ootwtries < 10:

                    c,movelist,rejectflag=outoftheway_(boxtomove,rcaxis,cbn,c,movelist,bf,nargout=3)
                    ootwtries=ootwtries + 1

                movedir=desireddirs[ind]
            c[cr,cc]=0
            if 1 == movedir:
                cc=cc + 1
            else:
                if 2 == movedir:
                    cr=cr + 1
                else:
                    if 3 == movedir:
                        cc=cc - 1
                    else:
                        if 4 == movedir:
                            cr=cr - 1
            c[cr,cc]=cbn
            movelist[movelist.shape[0] + 1,:]=[cbn,movedir]
            dr=fr - cr
            dc=fc - cc

    return movelist,c
def outoftheway_(boxnumber,rcaxis,dontmovetheseboxes,c,movelist,bf,nargout=1):
    c_in=copy_(c)
    movelist_in=copy_(movelist)
    rejectflag=0
    cr,cc=find_(c == boxnumber,nargout=2)
    neighborhood=matlabarray([c[cr,cc + 1],c[cr + 1,cc],c[cr,cc - 1],c[cr - 1,cc]])
    opendirs=find_(not neighborhood)
    if isempty_(opendirs):
        if - 1 == rcaxis:
            bettercandidates=neighborhood[[2,4]]
            worsecandidates=neighborhood[[1,3]]
        else:
            if 1 == rcaxis:
                bettercandidates=neighborhood[[1,3]]
                worsecandidates=neighborhood[[2,4]]
        wallnum=c[1,1]
        remainingcandidates=setdiff_(bettercandidates,[dontmovetheseboxes,wallnum])
        if isempty_(remainingcandidates):
            remainingcandidates=setdiff_(worsecandidates,[dontmovetheseboxes,wallnum])
            if isempty_(remainingcandidates):
                rejectflag=1
                c=copy_(c_in)
                movelist=copy_(movelist_in)
                return c,movelist,rejectflag
        if length_(remainingcandidates) > 1:
            remainingcandidates=remainingcandidates[(rand > 0.515) + 1]
        c,movelist,rejectflag=outoftheway_(remainingcandidates,- rcaxis,[dontmovetheseboxes,boxnumber],c,movelist,bf,nargout=3)
        if rejectflag:
            c=copy_(c_in)
            movelist=copy_(movelist_in)
            return c,movelist,rejectflag
        movedir=find_(neighborhood == remainingcandidates)
    else:
        cr,cc=find_(c == boxnumber,nargout=2)
        fr,fc=find_(bf == boxnumber,nargout=2)
        dr=fr - cr
        dc=fc - cc
        desireddirs=matlabarray([])
        if dr != 0:
            desireddirs[desireddirs.shape[0] + 1]=- sign_(dr) + 3
        if dc != 0:
            desireddirs[desireddirs.shape[0] + 1]=- sign_(dc) + 2
        pic=opendirs[ismember1_(opendirs,desireddirs)]
        if not isempty_(pic):
            if length_(pic) > 1:
                if abs_(dr) > abs_(dc):
                    movedir=desireddirs[1]
                else:
                    movedir=desireddirs[2]
            else:
                movedir=copy_(pic)
        else:
            movedir=opendirs[ceil_(rand * length_(opendirs))]
    c[cr,cc]=0
    if 1 == movedir:
        cc=cc + 1
    else:
        if 2 == movedir:
            cr=cr + 1
        else:
            if 3 == movedir:
                cc=cc - 1
            else:
                if 4 == movedir:
                    cr=cr - 1
    c[cr,cc]=boxnumber
    movelist[movelist.shape[0] + 1,:]=[boxnumber,movedir]
    return c,movelist,rejectflag
def ismember1_(a,s,nargout=1):
    numelA=numel_(a)
    numelS=numel_(s)
    if numelA == 0 or numelS <= 1:
        if (numelA == 0 or numelS == 0):
            tf=false_(size_(a))
            return tf
        else:
            if numelS == 1:
                tf=(a == s)
                return tf
    else:
        tf=false_(1,numelA)
        for i in arange_(1,numelA).reshape(-1):
            tf[i]=any_(a[i] == s)
    return tf
def ismember2_(a,s,nargout=1):
    numelA=numel_(a)
    numelS=numel_(s)
    if numelA == 0 or numelS <= 1:
        if (numelA == 0 or numelS == 0):
            tf=false_(size_(a))
            return tf
        else:
            if numelS == 1:
                tf=(a == s)
                return tf
    else:
        tf=false_(size_(a))
        for i in arange_(1,numelA).reshape(-1):
            found=(a[i] == s[:])
            if not any_(found):
                tf[i]=1
    return tf
def setdiff_(a,b,nargout=1):
    c=unique_(a[ismember2_(a[:],b[:])])
    return c
def unique_(a,nargout=1):
    numelA=numel_(a)
    if numelA < 2:
        b=copy_(a)
    else:
        b=sort_(a)
        db=diff_(b)
        d=db != 0
        d[numelA]=true
        b=b[d]
    return b
def sub2ind_(siz,varargin,*args,**kwargs):
    varargin = cellarray(args)
    nargin = len(args)+2
    siz=matlabarray([siz,ones_(1,nargin - length_(siz) - 1)])
    mt=cellfun_('isempty',varargin)
    if any_(mt):
        ndx=zeros_(not mt)
        return ndx
    k=matlabarray([1,cumprod_(siz[1:siz.shape[0] - 1])])
    ndx=1
    for i in arange_(1,length_(siz)).reshape(-1):
        v=varargin[i]
        ndx=ndx + (v - 1) * k[i]
    return ndx
def randperm_(n,nargout=1):
    DNC,p=sort_(rand_(1,n),nargout=2)
    return p
def perms_(V,nargout=1):
    V=V[:].T
    n=length_(V)
    if n <= 1:
        P=copy_(V)
        return P
    q=perms_(arange_(1,n - 1))
    m=size_(q,1)
    P=zeros_(n * m,n)
    P[1:m,:]=[n * ones_(m,1),q]
    for i in arange_(n - 1,1,- 1).reshape(-1):
        t=copy_(q)
        t[t == i]=n
        P[(n - i) * m + 1:(n - i + 1) * m,:]=[i * ones_(m,1),t]
    P=V[P]
    return P
def itTakesAThief_(ai,af,w,nargout=1):
    nBlocks=max_(ai[:])
    m,n=size_(ai,nargout=2)
    ftot=m * n
    steps=zeros_(ftot,4)
    steps[1,:]=[0,0,m,1]
    steps[m,:]=[0,- 1,m,0]
    steps[ftot - m + 1,:]=[- m,0,0,1]
    steps[ftot,:]=[- m,- 1,0,0]
    for ci in arange_(2,m - 1).reshape(-1):
        steps[ci,:]=[0,- 1,m,1]
    for ci in arange_(ftot - m + 2,ftot - 1).reshape(-1):
        steps[ci,:]=[- m,- 1,0,1]
    for col in arange_(m + 1,ftot - m,m).reshape(-1):
        steps[col,:]=[- m,0,m,1]
        steps[col + m - 1,:]=[- m,- 1,m,0]
        for row in arange_(1,m - 2).reshape(-1):
            steps[col + row,:]=[- m,- 1,m,1]
    I=matlabarray([0,1,0,- 1])
    J=matlabarray([1,0,- 1,0])
    a=copy_(ai)
    mv=matlabarray([])
    success=1
    uas=zeros_(m,n)
    initialmode=1
    while not isequal_(af,a):

        numw=length_(w)
        wwb=arange_(1,length_(w))
        wwbi=a[a == af]
        wwbi[wwbi == 0]=[]
        wwb[wwbi]=[]
        tmp,wwbi=sort_(- w[wwb],nargout=2)
        wwb=wwb[wwbi]
        if (success == 0):
            fiter=copy_(true)
        else:
            fiter=copy_(false)
        success=0
        while (wwb):

            blk=wwb[1]
            wwb[1]=[]
            ci=find_(af[:] == blk)
            if (a[ci] > 0 and not fiter and initialmode != 2):
                continue
            smv,fc,a=findshortestpath_(blk,a,af,w,m,n,1,[],steps,nargout=3)
            if (fc == 0):
                mv=matlabarray([[mv],[smv]])
                ci=find_(a[:] == blk)
                a[ci]=0
                ci=find_(af[:] == blk)
                a[ci]=blk
                success=1
            else:
                if (initialmode != 1):
                    moves=matlabarray([m,1,- m,- 1])
                    cpos=1
                    ci=find_(a[:] == blk)
                    if (initialmode == 0):
                        upos=copy_(cpos)
                        mfb=matlabarray([])
                        ua=copy_(uas)
                        uci=copy_(ci)
                        ua[uci]=1
                        while (upos <= size_(smv,1)):

                            uci=uci + moves[smv[upos,2]]
                            upos=upos + 1
                            ua[uci]=1
                            if (a[uci] > 0):
                                mfb=matlabarray([[mfb],[a[uci]]])

                        mfok,mfmv,a_mf=movefurniture_(mfb,wwb,a,af,w,m,n,ua,steps,nargout=3)
                        if (mfok):
                            mv=matlabarray([[mv],[mfmv],[smv]])
                            a=copy_(a_mf)
                            a[ci]=0
                            ci=find_(af[:] == blk)
                            a[ci]=blk
                            continue
                    a[ci]=0
                    chmv=matlabarray([])
                    while (cpos <= size_(smv,1)):

                        while (cpos <= size_(smv,1) and a[ci + moves[smv[cpos,2]]] == 0):

                            if (initialmode):
                                if af[ci + moves[smv[cpos,2]]] > 0:
                                    break
                            ci=ci + moves[smv[cpos,2]]
                            mv=matlabarray([[mv],[smv[cpos,:]]])
                            cpos=cpos + 1

                        if (initialmode):
                            break
                        if (cpos > size_(smv,1)):
                            continue
                        upos=copy_(cpos)
                        ua=copy_(uas)
                        uci=copy_(ci)
                        ua[uci]=1
                        while (upos <= size_(smv,1)):

                            uci=uci + moves[smv[upos,2]]
                            upos=upos + 1
                            ua[uci]=1

                        hmv,fc,a=findshortestpath_(a[ci + moves[smv[cpos,2]]],a,af,w,m,n,2,ua,steps,nargout=3)
                        if (isempty_(hmv)):
                            ua=zeros_(m,n)
                            ua[ci]=1
                            ua[ci + moves[smv[cpos,2]]]=1
                            hmv,fc,a=findshortestpath_(a[ci + moves[smv[cpos,2]]],a,af,w,m,n,2,ua,steps,nargout=3)
                        mv=matlabarray([[mv],[hmv]])
                        chmv=matlabarray([[chmv],[hmv]])
                        hpos=1
                        while (hpos <= size_(hmv,1)):

                            hci=find_(a[:] == hmv[hpos,1])
                            a[hci]=0
                            hci=hci + moves[hmv[hpos,2]]
                            a[hci]=hmv[hpos,1]
                            hpos=hpos + 1


                    a[ci]=blk

        if (not success and initialmode == 1):
            initialmode=0
            success=1
        if (not success and initialmode == 2):
            initialmode=0
            success=1

    return mv
def movefurniture_(mfb,wwb,a,af,w,m,n,ua,steps,nargout=1):
    fcs=0
    mfmv=matlabarray([])
    mfok=0
    a_mf=copy_(a)
    moves=matlabarray([m,1,- m,- 1])
    while (mfb):

        mblk=mfb[1]
        mfb[1]=[]
        mci=find_(a_mf[:] == mblk)
        hmv,fc,a_mf=findshortestpath_(mblk,a_mf,af,w,m,n,2,ua,steps,nargout=3)
        if (isempty_(hmv)):
            mfok=0
            return mfok,mfmv,a_mf,ua
        mfmv=matlabarray([[mfmv],[hmv]])
        hpos=1
        while (hpos <= size_(hmv,1)):

            hci=find_(a_mf[:] == hmv[hpos,1])
            a_mf[hci]=0
            hci=hci + moves[hmv[hpos,2]]
            a_mf[hci]=hmv[hpos,1]
            ua[hci]=1
            hpos=hpos + 1


    while (wwb):

        blk=wwb[1]
        wwb[1]=[]
        ci=find_(af[:] == blk)
        if (ua[ci]):
            continue
        hmv,fc,a_mf=findshortestpath_(blk,a_mf,af,w,m,n,1,[],steps,nargout=3)
        if (fc == 0):
            mfmv=matlabarray([[mfmv],[hmv]])
            ci=find_(a_mf[:] == blk)
            a_mf[ci]=0
            ci=find_(af[:] == blk)
            a_mf[ci]=blk

    mfok=1
    return mfok,mfmv,a_mf,ua
def findshortestpath_(blk,a,af,w,m,n,mode,ua,steps,nargout=1):
    finalmode=copy_(false)
    smv=matlabarray([])
    fc=0
    _is=zeros_(100,1)
    isi=1
    ise=1
    _is[1]=find_(a[:] == blk)
    ca=zeros_(m,n)
    ca[_is[1]]=1
    cm=zeros_(m,n)
    om=zeros_(m,n)
    fm=zeros_(m,n)
    helpw=matlabarray([[0],[w]])
    while (isi <= ise):

        ci=_is[isi]
        cv=ca[ci]
        t=ci + steps[ci,:]
        if (mode == 2):
            t[ua[t] == 1]=ci
        for ind in arange_(1,4).reshape(-1):
            mpenalty=0
            if (a[t[ind]] > 0):
                mpenalty=2 * helpw[a[t[ind]] + 1]
            if ca[t[ind]] == 0:
                ca[t[ind]]=cv + 1
                if (mode == 1):
                    cm[t[ind]]=cm[ci] + mpenalty + w[blk] + 0.1 * (a[t[ind]] > 0)
                else:
                    cm[t[ind]]=cm[ci] + 2 * helpw[a[t[ind]] + 1]
                om[t[ind]]=om[ci] + (a[t[ind]] > 0)
                fm[t[ind]]=a[ci]
                if (mode == 1 or a[t[ind]] > 0):
                    ise=ise + 1
                    _is[ise]=t[ind]
            else:
                if (cm[ci] + mpenalty + w[blk] < cm[t[ind]]):
                    ca[t[ind]]=ca[ci] + 1
                    cm[t[ind]]=cm[ci] + mpenalty + w[blk]
                    om[t[ind]]=om[ci] + (a[t[ind]] > 0)
                    fm[t[ind]]=a[ci]
                    if (mode == 1 or a[t[ind]] > 0):
                        ise=ise + 1
                        _is[ise]=t[ind]
        isi=isi + 1

    if (mode == 1):
        ci=find_(af[:] == blk)
    else:
        cm[ca == 0]=Inf
        mi=matlabarray([])
        if (finalmode):
            ui=find_(a == 0 and (af == 0 or af == blk))
            minval=min_(cm[ui])
            if (not isinf_(minval)):
                mi=find_(cm[ui] == minval)
        if (isempty_(mi) or isinf_(minval)):
            ui=find_(a == 0)
            minval=min_(cm[ui])
            mi=find_(cm[ui] == minval)
        if (length_(mi) > 1):
            minval=1e+20
            for cand in arange_(1,length_(mi)).reshape(-1):
                cci=ui[mi[cand]]
                cblk=fm[cci]
                row=mod_(cci,m)
                col=ceil_(cci / m)
                frow,fcol=find_(af == cblk,nargout=2)
                cblkcost=abs_(row - frow) + abs_(col - fcol)
                if (cblkcost < minval):
                    minval=copy_(cblkcost)
                    ci=copy_(cci)
        else:
            ci=ui[mi]
    cv=ca[ci]
    if (cv == 0):
        return smv,fc,a
    tmv=matlabarray([])
    while (cv > 1):

        t=ci + steps[ci,:]
        pi=find_(ca[t] == cv - 1)
        tmp,ni=min_(cm[t[pi]],nargout=2)
        ci=t[pi[ni]]
        if (mode == 1):
            tmv[tmv.shape[0] + 1,[1,2]]=[blk,pi[ni]]
        else:
            if (a[ci] > 0):
                tmv[tmv.shape[0] + 1,[1,2]]=[a[ci],pi[ni]]
        cv=cv - 1

    if (mode == 1):
        smv=matlabarray([tmv[tmv.shape[0]:- 1:1,:]])
        fc=om[find_(af[:] == blk)]
    else:
        smv=copy_(tmv)
        fc=0
    return smv,fc,a
def dealWall1_(ai,af,w,bestmv,nargout=1):
    yess=0
    aiMap=ai > 0
    nBlocks=length_(w)
    m,n=size_(aiMap,nargout=2)
    if nBlocks / (m * n) > 0.5:
        return bestmv,yess
    afMap=af > 0
    mapDif=(ai == af).dot(aiMap).dot(afMap)
    rsum=sum_(mapDif,2)
    csum=sum_(mapDif)
    hwall=rsum == n
    vwall=csum == m
    hwall[[1,m]]=0
    vwall[[1,n]]=0
    nzh=nnz_(hwall)
    nzv=nnz_(vwall)
    nzhv=nzh + nzv
    if nzhv != 1 or nzhv != 2:
        return bestmv,yess
    bestScore=sum_(w[bestmv[:,1]])
    aiBlock=ai[aiMap]
    aiOrder,aiPos=sort_(aiBlock,nargout=2)
    airow,aicol=find_(aiMap,nargout=2)
    airow=airow[aiPos]
    aicol=aicol[aiPos]
    I=matlabarray([0,1,0,- 1])
    J=matlabarray([1,0,- 1,0])
    if nzh == 1:
        hBrickID=ai[hwall,:]
        hwall=find_(hwall)
        brickWeight=w[hBrickID]
        minb,minInd=sort_(brickWeight,nargout=2)
        for i in arange_(1,2).reshape(-1):
            a=copy_(ai)
            openDoor=hBrickID[minInd[i]]
            di=airow[openDoor]
            dj=aicol[openDoor]
            if hwall < m / 2:
                ndi=di + I[2]
                ndj=dj + J[2]
                m1=2
            else:
                ndi=di + I[4]
                ndj=dj + J[4]
                m1=4
            if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                if hwall < m / 2 and hwall > 2:
                    ndi=di + I[4]
                    ndj=dj + J[4]
                    m1=4
                else:
                    ndi=di + I[2]
                    ndj=dj + J[2]
                    m1=2
                if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                    continue
            if dj < n / 2:
                ndi=ndi + I[1]
                ndj=ndj + J[1]
                m2=1
            else:
                ndi=ndi + I[3]
                ndj=ndj + J[3]
                m2=3
            if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                if dj < n / 2 and dj > 2:
                    ndi=ndi + I[3]
                    ndj=ndj + J[3]
                    m2=3
                else:
                    ndi=ndi + I[1]
                    ndj=ndj + J[1]
                    m2=1
                if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                    continue
            mvt=matlabarray([[[openDoor,m1]],[[openDoor,m2]]])
            a[di,dj]=0
            a[ndi,ndj]=openDoor
            aaf=copy_(af)
            aaf[di,dj]=0
            aaf[ndi,ndj]=openDoor
            mv1=cbest_(a,aaf,w)
            mvt=matlabarray([[mvt],[mv1],[[openDoor,4 - m2]],[[openDoor,6 - m1]]])
            curscore=sum_(w[mvt[:,1]])
            if curscore < bestScore:
                yess=1
                bestmv=copy_(mvt)
                bestScore=copy_(curscore)
    if nzv == 1:
        vBrickID=ai[:,vwall]
        vwall=find_(vwall)
        brickWeight=w[vBrickID]
        minb,minInd=sort_(brickWeight,nargout=2)
        for i in arange_(1,2).reshape(-1):
            a=copy_(ai)
            openDoor=vBrickID[minInd[i]]
            di=airow[openDoor]
            dj=aicol[openDoor]
            if vwall < n / 2:
                ndi=di + I[1]
                ndj=dj + J[1]
                m1=1
            else:
                ndi=di + I[3]
                ndj=dj + J[3]
                m1=3
            if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                if vwall < n / 2 and vwall > 2:
                    ndi=di + I[3]
                    ndj=dj + J[3]
                    m1=3
                else:
                    ndi=di + I[1]
                    ndj=dj + J[1]
                    m1=1
                if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                    continue
            if di < m / 2:
                ndi=ndi + I[2]
                ndj=ndj + J[2]
                m2=2
            else:
                ndi=ndi + I[4]
                ndj=ndj + J[4]
                m2=4
            if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                if di < m / 2 and di > 2:
                    ndi=ndi + I[4]
                    ndj=ndj + J[4]
                    m2=4
                else:
                    ndi=ndi + I[2]
                    ndj=ndj + J[2]
                    m2=2
                if a[ndi,ndj] != 0 or af[ndi,ndj] != 0:
                    continue
            mvt=matlabarray([[[openDoor,m1]],[[openDoor,m2]]])
            a[di,dj]=0
            a[ndi,ndj]=openDoor
            aaf=copy_(af)
            aaf[di,dj]=0
            aaf[ndi,ndj]=openDoor
            mv1=cbest_(a,aaf,w)
            mvt=matlabarray([[mvt],[mv1],[[openDoor,6 - m2]],[[openDoor,4 - m1]]])
            curscore=sum_(w[mvt[:,1]])
            if curscore < bestScore:
                yess=1
                bestmv=copy_(mvt)
                bestScore=copy_(curscore)
    mv=copy_(bestmv)
    return bestmv,yess
