3D ASCII块构建


82

挑战

编写一个程序,该程序采用11x11整数数组,并构建3D ASCII块构建,其中数组中的每个值表示在与数组位置匹配的坐标处的一列块的高度。负高度是“浮动”列-仅顶部块可见。

                                                        __________________
                                        ___            /\__\__\__\__\__\__\
 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /\__\          /\/\__\__\__\__\__\__\
 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /\/__/         /\/\/__/__/__/__/__/__/
 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /\/\__\        /\/\/\__\      /\/\/__/
 1, 0, 0, 7,-7,-7,-7,-7, 7, 0, 0,    \/\/\__\      /\/\/\/__/     /\/\/__/
 0, 0, 0, 7,-7,-7,-7,-7, 7, 0, 0,     \/\/__/     /\/\/\/\__\    /\/\/__/
 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,      \/\__\    /\/\/\/\/__/   /\/\/__/
 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,       \/__/    \/\/\/\/\__\_  \/\/__/
 1, 0, 0, 4, 3, 2, 1, 0, 0, 0, 1,                 \/\/\/\/__/_\_ \/__/
 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,            ___   \/\/\/__/__/_\_         ___
 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,           /\__\   \/\/__/__/__/_\       /\__\
 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,           \/\__\   \/__/__/__/__/       \/\__\
                                             \/\__\_________         ______\/\__\
                                              \/\__\__\__\__\       /\__\__\__\__\
                                               \/__/__/__/__/       \/__/__/__/__/

输入值

输入将是一个由121个整数组成的列表,可以从stdin中读取(由您选择分隔符),也可以作为数组传入(可以是1D或2D)。

高度将在-11到11之间。

输出量

可以将生成的建筑物写入stdout,直接在屏幕上显示,或者以换行符分隔的字符串形式返回。

允许前导和尾随空格。

建筑规则

单个3D块的形状如下所示:

 ___
/\__\
\/__/

一个2x2x2的方块立方体看起来像这样:

  ______
 /\__\__\
/\/\__\__\
\/\/__/__/
 \/__/__/

当块重叠时,较高的块优先于较低的块,前面的块优先于后面的块,而左边的块优先于右边的块。唯一的特殊情况是,块的顶行绝对不能覆盖其后面的任何非空格字符。

可以通过从侧面查看2D表示来最好地解释列高。

HEIGHT:  1    2    3   -3   -2   -1
                  __   __
             __  |__| |__|  __
        __  |__| |__|      |__|  __
       |__| |__| |__|           |__|

测试用例

如果您想在更多输入上尝试解决方案,我在这里整理了几个测试用例。

获奖

这是,因此最短的提交(以字节为单位)获胜。


9
噢,男孩,准备好使用300多个字节的解决方案。好挑战。+1
完全人类的

7
@totallyhuman Nah,Dennis将在20分钟内为此提供9字节的解决方案。
执事

3
透视图是否必须与前景中输入数据的左下方所示相同?这不是数据的第一个或最后一个元素,这使它变得更难。1.保持映射不变,并在前景的右下角绘制输出,还是2.绘制镜像或数据旋转90度,是否可以接受?这些方法中的任何一个都会使最后一个数据元素与前景中的列相对应,这会更容易。
水平河圣

3
我觉得倾向于使用真实的游戏引擎(或其一部分)来渲染照片并将其转换为ASCII
Stan Strum,

@LevelRiverSt这似乎是一个合理的请求-您可以选择121个输入元素的顺序,只要您的顺序是一致的,就可以选择最适合您的解决方案的顺序。必须能够生成可以使用默认顺序生成的各种布局。
James Holderness

Answers:


25

木炭70 69 68字节

≔E¹¹⮌I⪪S,θF²F¹¹F¹¹F¹¹«J⁻⁻⁺λκ×μ³ι⁻λκ≔§§θλμη¿∨⁼±η⊕κ‹κη¿ι“↗⊟&⁹κUhnI”___

在线尝试!链接是详细版本的代码。说明:

≔E¹¹⮌I⪪S,θ

读取数组,将每行用逗号分隔并转换为整数,但也要反转每一行,因为我们要从右到左绘制,以使左列覆盖右列。(其他尺寸已经具有所需的覆盖行为。)

F²F¹¹F¹¹F¹¹«

遍历i)顶行和正文k)高度l)行m)列。(在第一顶线和正文之间循环,避免用顶线覆盖正文。)

J⁻⁻⁺λκ×μ³ι⁻λκ

跳到多维数据集的位置。

≔§§θλμη

获取当前行和列的高度。

¿∨⁼±η⊕κ‹κη

测试是否应为此行和列在此高度绘制一个多维数据集。

¿ι“↗⊟&⁹κUhnI”___

绘制主体或立方体的顶部。


当我将第一个3改为a时33,塔中只有11个方块。在一般情况下,塔楼的上限似乎是11。
FabianRöling18年

@Fabian我有点困惑,这F¹¹F¹¹F¹¹不是一个线索……
Neil

我不懂这种编程语言,我只是在玩TIO链接。
FabianRöling18年

30

C, 376个   350   313   309  285字节

感谢@Jonathan Frech节省了四个字节!

#define F for(
char*t,G[26][67],*s;i,j,e,k,v,x,y;b(){F s="\\/__//\\__\\ ___ ";*s;--y,s+=5)F e=5;e--;*t=*s<33&*t>32?*t:s[e])t=G[y]+x+e;}f(int*M){F;e<1716;++e)G[e/66][e%66]=32;F k=0;++k<12;)F i=0;i<11;++i)F j=11;j--;v+k||b())x=i+j*3+k,y=14+i-k,(v=M[i*11+j])>=k&&b();F;++e<26;)puts(G+e);}

在线尝试!

展开:

#define F for(

char *t, G[26][67], *s;
i, j, e, k, v, x, y;

b()
{
    F s="\\/__//\\__\\ ___ "; *s; --y, s+=5)
        F e=5; e--; *t=*s<33&*t>32?*t:s[e])
            t = G[y]+x+e;
}

f(int*M)
{
    F; e<1716; ++e)
        G[e/66][e%66] = 32;

    F k=0; ++k<12;)
        F i=0; i<11; ++i)
            F j=11; j--; v+k||b())
                x = i+j*3+k,
                y = 14+i-k,
                (v=M[i*11+j])>=k && b();

    F; ++e<26;)
        puts(G+e);
}

26*66不能1716
乔纳森·弗雷希

@JonathanFrech当然,我忘记了这一点。
Steadybox

*s==32-> *s<33
乔纳森·弗雷希

for(e=k=1;e;++k)for(e=-> for(k=1;e;++k)for(e=
乔纳森·弗雷希

#define B b(...)&++e-> #define B++e&b(...)(假设b不依赖e,我认为不依赖)。
乔纳森·弗雷希

9

的JavaScript(ES6),277个 251字节

a=>(n=55,$=f=>[...Array(n)].map((_,i)=>f(i)),S=$(_=>$(_=>' ')),n=11,$(l=>$(z=>$(y=>$(x=>(x=10-x,X=x*3+y+z,Y=y-z+n,Z=a[y][x])<=z&&Z+z+1?0:l?['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s)):S[Y].splice(X+1,3,...'___'))))),S.map(r=>r.join``).join`
`)

@Neil的建议中保存了26个字节。

不打高尔夫球

a=>(
    n=55,
    $=f=>[...Array(n)].map((_,i)=>f(i)),
    S=$(_=>$(_=>' ')),
    n=11,
    $(l=>
        $(z=>$(y=>$(x=>(
            x=10-x,
            X=x*3+y+z,
            Y=y-z+n,
            Z=a[y][x],
            Z<=z && Z+z+1 || (
                l
                ? ['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s))
                : S[Y].splice(X+1,3,...'___')
            )
        ))))
    ),
    S.map(r=>r.join``).join`\n`
)

2
,$(w=>$(z=>$(y=>$(x=>(Z=a[y][x=10-x,X=x*3+y+z,Y=y-z+n,x])<=z&&Z+z+1?0:w?['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s)):S[Y].splice(X+1,3,...'___'))))),似乎节省了26个字节。
尼尔,

@尼尔灿烂!首先绘制所有顶线可以避免检查非空格的麻烦。
darrylyeo

6

Python 2,243字节

a=input()
s=eval(`[[' ']*55]*23`)
for h in range(7986):
 k=h%3;x=h/3%11;y=h/33%11;z=h/363%11;i=h/3993;u=y+z-x*3+30;v=y-z+10
 if~-(z>=a[y][10-x]!=~z):
	if i*k:s[v+k][u:u+5]='\//\____/\\'[k%2::2]
	if~-i:s[v][u+1+k]='_'
for l in s:print''.join(l)

在线尝试!

Neil的木炭方法的Python翻译。


很高兴看到一个经过实践检验的Python解决方案。我的Python概念验证超过900个字节!
James Holderness

3
+1+k-> -~k
乔纳森·弗雷奇


5

Tcl,380409字节

用户sergiol一直在忙着很好地解决这个问题:

set X [read stdin]
proc L {a b c d e s} {time {incr z
set y -1
time {incr y
set x -1
time {if {abs([set Z [lindex $::X [expr ($y+1)*11-[incr x]-1]]])==$z|$z<$Z} {set s [string repl [string repl $s [set i [expr -3*$x+57*$y-55*abs($z)+701]] $i+$b $a] [incr i $c] $i+$e $d]}} 11} 11} 12
set s}
puts [L /\\__\\ 4 56 \\/__/ 4 [L "" -1 -55 ___ 2 [string repe [string repe \  55]\n 23]]]

在线尝试!

原始内容

set xs [read stdin]
proc L {a b c d e s} {set z 0
while {[incr z]<12} {set y -1
while {[incr y]<11} {set x -1
while {[incr x]<11} {set Z [lindex $::xs [expr ($y+1)*11-$x-1]]
if {abs($Z)==$z||$z<$Z} {set i [expr -3*$x+57*$y-55*abs($z)+701]
set s [string repl [string repl $s $i $i+$b $a] [incr i $c] $i+$e $d]}}}}
set s}
puts [L /\\__\\ 4 56 \\/__/ 4 [L "" -1 -55 ___ 2 [string repe [string repe \  55]\n 23]]]

在线尝试!

las,就是这样。“脱胶”只是眼中的一点点轻松

set s [string repeat [string repeat " " 55]\n 23]

proc loops {s0 i0 io s1 i1} {
  set z  0; while {[incr z] < 12} {
  set y -1; while {[incr y] < 11} {
  set x -1; while {[incr x] < 11} {
    set Z [lindex $::xs [expr {($y+1) * 11 - $x - 1}]]
    if {abs($Z) == $z || $z < $Z} {
        set i [expr {-3*$x + 57*$y - 55*abs($z) + 701}]
        set ::s [string replace $::s $i $i+$i0 $s0]
        incr i $io
        set ::s [string replace $::s $i $i+$i1 $s1]
    }
  } } }
}

loops ""      -1 -55 \
       ___     2
loops /\\__\\  4  56 \
      \\/__/   4

puts $s

根据要求构建一个字符串。从标准输入中获取数组。从下到上,从前到后,从右到左遍历字符串数据。分两次通过一次,一次用于顶部边缘,另一次用于每个立方体的其余部分。

我尝试使用一些甜美的功能性lambda mojo使其更小,但是可惜,它使它更大。


您可以打高尔夫球:tio.run/…–
sergiol

更多高尔夫活动:tio.run/…–
sergiol


还有更多:tio.run/…–
sergiol

更多信息:tio.run
##
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.