def equilibre(texte, n, m):
    firstWord = texte[0][:]
    texte.pop(0)
    a = bruteForceWithTransition(texte, [[firstWord]], blancLigne([firstWord], n), n)
    b = bruteForceWoTransition(texte, [[firstWord]], blancLigne([firstWord], n), n)
    if(a[2] < b[2]):
        #print a[1]
        return a[1],a[2]
    else:
        #print b[1]
        return b[1],b[2]
def fusionTextes(text1, text2, textm1, textm2, stringLength): #O(1)
    fusionedString = text1[-1][:] + text2[0][:] #O(1)
    if(possibleString(fusionedString, stringLength)):
        t1 = text1[:] #O(1)
        t2 = text2[:] #O(1)
        fm = blancLigne(fusionedString ,stringLength)
        m1 = blancLigne(text1[-1], stringLength)
        m2 = blancLigne(text2[0], stringLength)
        newM = (textm1 - m1) + (textm2 - m2) + fm
        
        if(len(text1)>0):
            text1.pop() #O(1)
        if(len(text2)>0):
            text2.pop(0) #O(1)
        resultText = text1 + [fusionedString] + text2 #O(1)

        return True, newM, resultText #O(1)
    else:
        return False,0,[]
def equilibre_reccur(texte, n, ind):
    res=([],0)
    if longueur(texte)<=n: #si la longueur du texte est inférieur à la longueur de la ligne
        res=([texte],0) #alors pas besoin de le découper, et on ignore le déséquilibre
        MEMO.add(ind,res[0],res[1])
    else :
        curr=0
        s='infini'
        while longueur(texte[0:curr+1])<=n:
            reccur=MEMO.get(ind+curr+1)
            if reccur==-1:
                reccur=equilibre_reccur(texte[curr+1:],n,ind+curr+1)
                MEMO.add(ind+1,reccur[0],reccur[1])
            s1=blancLigne(texte[0:curr+1],n)+reccur[1]
            if min(s1,s)==s1:
                s=s1
                res=([texte[0:curr+1]]+reccur[0],s)
            curr+=1
    return res
def equilibre(texte,n):
    global MEMO
    MEMO=Memo()
    for i in range (len(texte)-1,-1,-1):    #Pour i allant de l'indice du dernier mot au premier
        if longueur(texte[i:])<=n:
            res=([texte[i:]],0)        
        else:
            curr=0
            deseq='infini'
            while longueur(texte[i:i+curr+1])<=n:
                suite=MEMO.get(i+curr+1)
                deseq_bis=blancLigne(texte[i:i+curr+1],n)+suite[1]
                if min(deseq,deseq_bis)==deseq_bis: #on notera que la fonction min a été surchargée pour
                                                    #considérer 'infini' comme l'infini
                    deseq=deseq_bis
                    res=([texte[i:i+curr+1]]+suite[0],deseq)
                curr+=1
        MEMO.add(i,res[0],res[1])
    return res
def bruteForceWithTransition(words, text, measure, strl):
    if(words == []):
        return [],text,measure,strl
    else:
        text.append([words[0]])
        newText = text[:]
        newText2 = text[:]
        newMeasure = measure + blancLigne([words[0]], strl)
        newWords = words[:]
        if(type(newWords) is str):
            newWords = []
        else:
            newWords.pop(0)
        
        a = bruteForceWithTransition(newWords, newText, newMeasure, strl)
        b = bruteForceWoTransition(newWords, newText2, newMeasure, strl)
        
        if(a[2] < b[2]):
            return a
        else:
            return b
def equilibre(words, stringLength): #O(n^3)
    wordsCount = len(words)
    #La matrice qui contient tous les poids des configurations de texte differentes.
    #Initialise par maxInt
    weightMatrix = [[sys.maxint for _ in xrange(wordsCount)] for _ in xrange(wordsCount)]

    #La matrice qui contient les souslignes de textes pour chaque pas de programmation dynamique
    #Initialisee par listes vides
    stringMatrix = [[[] for _ in xrange(wordsCount)] for _ in xrange(wordsCount)]

    #Le parcours des diagonales commenceant d'element [0][0]
    k = 0;
    m = wordsCount;
    for s in range(0, m): #O(n^2/2)
        for i in range(k, wordsCount):
            j = i-k
            #print "###########################"
            #print "## Working with case",i,j,"##"
            #print "###########################"

            #Remplissage des diagonales
            if(i==j):
            #Remplissage des diagonales principales par mots seuls et poids des lignes avec un seul mot
                #print "Filling main diagonal case"
                weightMatrix[i][j] = blancLigne([words[i]], stringLength) #O(1)
                stringMatrix[i][j] = [[words[i]]] #O(1)
                #print "Weight of case", weightMatrix[i][j]
                #print "String in case", stringMatrix[i][j]
            else:
                #Remplissage des autres diagonales

                #Essayons de construire une nouvelle partie de texte a partir des construites les plus optimales
                #On peut concatener soustextes ou fusionner la derniere ligne de premier soustexte et premier ligne de deuxieme soustexte
                #en les concatenant si c'est possible
                column = j+1
                for row in range(j, i): #O(n)
                    #print "-----------------------------------------------------------------"
                    #Concatenations des soustextes
                    #print "Working with case ", row,j, " with text", stringMatrix[row][j]
                    #print "and case", i, column," with text", stringMatrix[i][column]
                    s = weightMatrix[row][j] + weightMatrix[i][column] #O(1)
                    
                    #print "*****************************************************************"
                    #print "Concatenation of these texts weights ", s
                    if(s < weightMatrix[i][j]):
                        #print "which is less than current value of case",weightMatrix[i][j]
                        weightMatrix[i][j] = s #O(1)
                        stringMatrix[i][j] = stringMatrix[row][j] + stringMatrix[i][column] #O(1)
                        #print "So, new text is", stringMatrix[i][j]
                    #else:
                        #print "But it's greater than the value already in case"
                    
                    #print "*****************************************************************"
                    #Essai de fusion des soustextes
                    fusion = fusionTextes(stringMatrix[row][j][:], stringMatrix[i][column][:], weightMatrix[row][j], weightMatrix[i][column], stringLength) #O(1)
                    #print "Now, I'm trying to make a fusion of textes in this cases: "
                    if(fusion[0] and fusion[1] < weightMatrix[i][j]):
                        #print "It's possible and the weight of this fusion is ", fusion[1]
                        #print "The text in the case is", fusion[2]
                        weightMatrix[i][j] = fusion[1] #O(1)
                        stringMatrix[i][j] = fusion[2] #O(1)
                    #else:
                        #print "But it's impossible or the weight of new text:",fusion[1]
                        #print "is greater than current: ",weightMatrix[i][j]
                    column = column + 1

        k = k+1;
        m = m-1;

    #print stringMatrix[wordsCount-1][0]
    #print weightMatrix[wordsCount-1][0]
    return stringMatrix[wordsCount-1][0], weightMatrix[wordsCount-1][0]