Stackin 'Boards

11

Tengo un montón de tablas que necesito apilar en el menor espacio posible. Desafortunadamente, los tableros se caen si los apilo a más de 10 de altura. Necesito un programa que me diga cómo apilar las tablas para ocupar el menor espacio horizontal posible, sin apilar tablas de más de diez de altura, o tener tablas colgando sobre el espacio vacío.

Tu tarea:

Escriba un programa o función, que cuando se le da una matriz que contiene las longitudes de los tableros, genera como ASCII la forma de apilar los tableros para conservar tanto espacio horizontal como sea posible, sin apilar los tableros de más de 10 de altura o tener cualquier parte de cualquier Junta colgando sobre el espacio vacío. Su arte ASCII debe mostrar la configuración de los tableros, cada uno con un carácter diferente. Habrá un máximo de 20 tableros. Por ejemplo, si la entrada fue [2,2,4,2,2,4,4,4], una salida posible es:

dhh
dgg
dff
dee
abc
abc
abc
abc

que es una configuración estable (aunque esto se caería en ~ 0.1 segundos en la vida real).

Entrada:

Una matriz que contiene hasta 20 enteros, que muestra las longitudes de los tableros.

Salida:

Arte ASCII que muestra las configuraciones de los tableros, como se describe anteriormente.

Casos de prueba:

Tenga en cuenta que puede haber otras soluciones para los casos de prueba, y los caracteres que se muestran para cada placa pueden 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

Puntuación:

Este es el , el puntaje más bajo en bytes gana

Grifo
fuente

Respuestas:

3

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

Increíblemente mal tiempo de ejecución, terminará en algún 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]

Pruébalo en línea!

Editar: - 2 -8 bytes gracias a @Mr. Edición de Xcoder : -8 bytes gracias a @notjagan

Explicación

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 ejecutable en TIO para algunos de los casos de prueba

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]

Pruébalo en línea!

Ambas soluciones probablemente podrían jugarse bastante.

Halvard Hummel
fuente
483 bytes
Sr. Xcoder
Sr. Xcoder, el segundo puede reducirse en cerca de 50 bytes, simplemente no he aplicado los cambios para el primero al segundo
Halvard Hummel
Sé que el segundo se puede jugar mucho al golf, pero los cambios en el primero deberían ser útiles.
Sr. Xcoder
1
Te ganaste mi voto positivo, por un gran código con una explicación maravillosa, que muestra mucho esfuerzo y reflexión. ¡Felicidades y bienvenidos a PPCG!
Sr. Xcoder