We’re rewarding the question askers & reputations are being recalculated! Read more.

11 added 90 characters in body

# Python 3, 513512511509499497485465459458458 444 bytes

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(map(lambda x:j(x)==j(d),for x in p[h:h+a]))and *(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(map(lambda x:x[~u]if~u<j9-u<j(x)else"and ",x[9-u]or" "for x in b))for u in c(-10,0)),b][o>97]


Edit: -2 -8 bytes thanks to @Mr. Xcoder Edit: -8 bytes thanks to @notjagan

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)<10and all(map<10)*all(lambda x:j(x)==j(d),for x in p[h:h+a]))and *(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(map(lambda x:x[~u]if~u<j9-u<j(x)else"and ",x[9-u]or" "for x in b))for u in c(-10,0)),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, 513512511509499497485465459458 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[~u]if~u<j(x)else" ",b))for u in c(-10,0)),b][o>97]


Try it online!

Edit: -2 -8 bytes thanks to @Mr. Xcoder

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[~u]if~u<j(x)else" ",b))for u in c(-10,0)),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, 513512511509499497485465459458 444 bytes

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]


Try it online!

Edit: -2 -8 bytes thanks to @Mr. Xcoder Edit: -8 bytes thanks to @notjagan

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

10 [Edit removed during grace period]; added 21 characters in body

# Python 3, 513512511509499497485465459459 458 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<jx[~u]if~u<j(x)else" ",b))for u in c(9,-110,-10)),b][o>97]

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<jx[~u]if~u<j(x)else" ",b))for u in c(9,-110,-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, 513512511509499497485465459 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),b][o>97]


Try it online!

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),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, 513512511509499497485465459 458 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[~u]if~u<j(x)else" ",b))for u in c(-10,0)),b][o>97]


Try it online!

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[~u]if~u<j(x)else" ",b))for u in c(-10,0)),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

9 added 27 characters in body

# Python 3, 513512511509499497485465465 459 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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]p+[l*a])
b=r(p[:]+[l]*ap+[l]*a)
return["\n".join("".join(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),b][o>97]


Edit: -22 -8 bytes thanks to @Mr. Xcoder

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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]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]*ap+[l]*a)
# Try to place the current horizontally to the right of the current stack
return["\n".join("".join(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),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, 513512511509499497485465 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),b][o>97]


Try it online!

Edit: -2 bytes thanks to @Mr. Xcoder

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),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, 513512511509499497485465 459 bytes

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(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),b][o>97]


Try it online!

Edit: -2 -8 bytes thanks to @Mr. Xcoder

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)<10and all(map(lambda x:j(x)==j(d),p[h:h+a]))and 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(map(lambda x:x[u]if u<j(x)else" ",b))for u in c(9,-1,-1)),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

8 deleted 100 characters in body
7 added 16 characters in body
6 added 16 characters in body
5 added 17 characters in body
4 added 17 characters in body
3 added 19 characters in body
2 added 1823 characters in body
1