堆叠板


11

我有一堆板,需要在尽可能小的空间内堆叠。不幸的是,如果我叠放超过10块高的木板,它们就会掉下来。我需要一个程序来告诉我如何堆叠电路板,以使其占用尽可能少的水平空间,而又不堆叠超过十个高的电路板,或者使电路板悬空在空的空间上。

你的任务:

编写一个程序或函数,当给定包含板长的数组时,以ASCII艺术形式输出堆叠板以节省尽可能多的水平空间的方式,而不会堆叠超过10层高的板或任何板的任何部分板闲逛在空的空间。您的ASCII艺术作品应显示板子的配置,每块板子使用不同的字符显示。最多有20个板。例如,如果输入为[2,2,4,2,2,4,4,4,4],则可能的输出为:

dhh
dgg
dff
dee
abc
abc
abc
abc

这是一个稳定的配置(尽管在现实生活中,它会在约0.1秒内掉落)。

输入:

一个包含最多20个整数的数组,显示木板的长度。

输出:

如上所述,显示板配置的ASCII文字。

测试用例:

请注意,对于测试用例,可能还有其他解决方案,并且每块板上显示的字符可能不同。

[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

得分:

这是,最低得分(以字节为单位)获胜

Answers:


3

Python 3中513 512 511 509 499 497个 485 465 459 458 444字节

令人难以置信的糟糕的运行时,将在某个时候结束

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]

在线尝试!

编辑:-2 -8字节感谢@Mr。Xcoder 编辑:-8个字节,感谢@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

Python 3,587字节

在某些测试案例中实际上可以在TIO上运行

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]

在线尝试!

两种解决方案都可以打很多。




Xcoder先生,第二个编码器可以减少近50个字节,我只是没有将第一个编码器的更改应用到第二个
编码器

我知道第二个可以打很多球,但是对第一个的改变应该会有所帮助。
Xcoder先生17年

1
您赢得了我的赞誉,获得了一些很棒的代码,并给出了很好的解释,这表明了我的努力和思想。恭喜,欢迎来到PPCG!
Xcoder先生17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.