Stackin 'Boards

11

Eu tenho um monte de pranchas que preciso empilhar no menor espaço possível. Infelizmente, as tábuas caem se eu as empilhar mais de 10. Preciso de um programa para me dizer como empilhar as tábuas para ocupar o menor espaço horizontal possível, sem empilhar tábuas com mais de dez metros de altura ou com tábuas penduradas no espaço vazio.

Sua tarefa:

Escreva um programa ou função que, quando fornecida uma matriz que contenha os comprimentos das placas, produza como ASCII a maneira de empilhar as placas para conservar o máximo de espaço horizontal possível, sem empilhar as placas com mais de 10 metros de altura ou ter qualquer parte de qualquer placa pendurada para fora sobre o espaço vazio. Sua arte ASCII deve mostrar a configuração das placas, com cada uma delas mostrando um caractere diferente. Haverá no máximo 20 placas. Por exemplo, se a entrada foi [2,2,4,2,2,4,4,4], uma saída possível é:

dhh
dgg
dff
dee
abc
abc
abc
abc

que é uma configuração estável (embora isso caia em ~ 0,1 segundos na vida real).

Entrada:

Uma matriz contendo até 20 números inteiros, mostrando os comprimentos das placas.

Resultado:

Arte ASCII mostrando as configurações das placas, conforme descrito acima.

Casos de teste:

Observe que pode haver outras soluções para os casos de teste e os caracteres mostrados para cada quadro podem ser diferentes.

[12,2,2,2,3,4,4,8,8]        -> ffgghhiii
                               ddddeeeeeeee
                               bbbbbbbbcccc
                               aaaaaaaaaaaa

[4,4,4,4,4,4,4,4,4,4,4,4]   -> llll
                               aaaa
                               cfghk
                               cfghk
                               cfghk
                               cfghk
                               debij
                               debij
                               debij
                               debij

[4,4,4,4,4,4,3,3,3,2,2,2,1] -> jjml
                               iiil
                               hhhk
                               gggk
                               ffff
                               eeee
                               dddd
                               cccc
                               bbbb
                               aaaa

Pontuação:

Isso é , a menor pontuação em bytes ganha

Gryphon
fonte

Respostas:

3

Python 3 , 513 512 511 509 499 497 485 465 459 458 444 bytes

Tempo de execução incrivelmente ruim, terminará em algum momento

e,j,c=enumerate,len,range
def f(n,p=[],o=97):
    r,l,m=lambda x:min(b,f(n[:i]+n[i+1:],x,o+1),key=j),chr(o),j(p)
    b=[p,l*(sum(n)*2+m)][n>[]]
    for i,a in e(n):
        for h,d in e(p):
            if a<11-j(d):b=r([p[f]+l*a*(f==h)for f in c(m)])
            if(j(d)<10)*all(j(x)==j(d)for x in p[h:h+a])*(a<=m-h):b=r([p[f]+l*(h<=f<h+a)for f in c(m)])
        if a<11:b=r(p+[l*a])
        b=r(p+[l]*a)
    return["\n".join("".join(9-u<j(x)and x[9-u]or" "for x in b)for u in c(10)),b][o>97]

Experimente online!

Edit: - 2 -8 bytes graças a @Mr. Xcoder Edit: -8 bytes graças a @notjagan

Explicação

e,j,c=enumerate,len,range      
         # These built-ins are used a lot
def f(n,p=[],o=97):
         # n is the remaining blocks
         # p is the current stack
         # o is the ASCI code for the next letter to use
    r,l,m=lambda x:min(b,f(n[:i]+n[i+1:],x,o+1),key=j),chr(o),j(p)
         # r is the recursive call, that also selects the smallest stack found
         # l is the letter to use next
         # m is the length of the current stack
    b=[p,l*(sum(n)*2+m)][n>[]]
         # Sets the current best, if there are no remaining blocks, select the found stack, else we set it to be worse than the possible worst case
    for i,a in e(n):
         # Loop through all the remaining blocks
        for h,d in e(p):
         # Loop through all the columns in the current stack
            if a<11-j(d):b=r([p[f]+l*a*(f==h)for f in c(m)])
         # If we can place the current block vertically in the current column, try it
            if(j(d)<10)*all(j(x)==j(d)for x in p[h:h+a])*(a<=m-h):b=r([p[f]+l*(h<=f<h+a)for f in c(m)])
         # If we can place the current block horizontally starting in the current column, try it
        if a<11:b=r(p+[l*a])
         # If the current block is lower than 10, try place it vertically to the right of the current stack
        b=r(p+[l]*a)
         # Try to place the current horizontally to the right of the current stack
    return["\n".join("".join(9-u<j(x)and x[9-u]or" "for x in b)for u in c(10)),b][o>97]
         # Return the best choice if we aren't in the first call to the function, that is the next letter is a. Else return the found best option formatted as a string

Python 3 , 587 bytes

Realmente executável no TIO para alguns dos casos de teste

e,j,c=enumerate,len,range
def f(n,p=[],o=97,b=[]):
    if(not n):return p
    if not b:b="a"*sum(n)*2
    r,q,s,l,m=lambda x:q(f(n[:i]+n[i+1:],x,o+1,b)),lambda x:[b,x][j(b)>j(x)],b,chr(o),j(p)
    if j(b)<=m:return b
    for i,a in e(n):
        for h,d in e(p):
            if a<11-j(d):b=r([p[f]+l*a*(f==h)for f in c(m)])
            if j(d)<10 and a<=m-h and all(map(lambda x:j(x)==j(d),p[h:h+a])):b=r([p[f]+l*(h<=f<h+a)for f in c(m)])
        if s==b:
            if a<11and m+1<j(b):b=r(p[:]+[l*a])
            if m+a<j(b):b=r(p[:]+[l for r in c(a)])
    return["\n".join("".join(map(lambda x:" "if u>=j(x)else x[u],b))for u in c(9,-1,-1)),b][o>97]

Experimente online!

Ambas as soluções provavelmente poderiam ser um pouco jogadas de golfe.

Halvard Hummel
fonte
483 bytes
Sr. Xcoder
583 bytes para o segundo #
Mr. Xcoder 05/08
Mr. Xcoder, o segundo pode ser reduzido em perto de 50 bytes, eu só havn't aplicado as alterações para o primeiro para o segundo
Halvard Hummel
Eu sei que o segundo pode ser muito jogado, mas as alterações no primeiro devem ser úteis.
Xcoder
1
Você ganhou meu voto positivo, por um ótimo código com uma explicação maravilhosa, que mostra muito esforço e pensamento. Parabéns e bem-vindo ao PPCG!
Xcoder