ASCII希尔伯特曲线


23

给定一个整数n输出,使用字符和,以ASCII n形式对Hilbert曲线进行第三次迭代。_|

这是前4个迭代:

n=1
 _ 
| |

n=2
 _   _ 
| |_| |
|_   _|
 _| |_

n=3
 _   _   _   _ 
| |_| | | |_| |
|_   _| |_   _|
 _| |_____| |_ 
|  ___   ___  |
|_|  _| |_  |_|
 _  |_   _|  _ 
| |___| |___| |

n=4
 _   _   _   _   _   _   _   _ 
| |_| | | |_| | | |_| | | |_| |
|_   _| |_   _| |_   _| |_   _|
 _| |_____| |_   _| |_____| |_ 
|  ___   ___  | |  ___   ___  |
|_|  _| |_  |_| |_|  _| |_  |_|
 _  |_   _|  _   _  |_   _|  _ 
| |___| |___| |_| |___| |___| |
|_   ___   ___   ___   ___   _|
 _| |_  |_|  _| |_  |_|  _| |_ 
|  _  |  _  |_   _|  _  |  _  |
|_| |_| | |___| |___| | |_| |_|
 _   _  |  ___   ___  |  _   _ 
| |_| | |_|  _| |_  |_| | |_| |
|_   _|  _  |_   _|  _  |_   _|
 _| |___| |___| |___| |___| |_ 

澄清说明

  • 我的问题类似于“ 绘制希尔伯特曲线”“使用斜线绘制希尔伯特曲线”
  • 下划线(之间的转换_()和竖线|)是u=2*v-1其中 u是的数目_S和v是多少|秒。
  • 为了与原始帖子保持一致,曲线必须在底部开始并结束。
  • 您可以拥有完整的程序或功能。
  • 输出到stdout(或类似的东西)。
  • 您可以有前导或尾随空格,输出只需对齐即可,使其看起来像示例一样。
  • 这是代码高尔夫球,因此最短答案以字节为单位。

3
您能否在您的帖子中包括希尔伯特曲线的定义,以及有关如何构造ASCII版本的确切规范?
Loovjo

@Bobas_Pett:不是kolmogorov复杂度
shooqie


@Loovjo我在“说明”下加了下划线(_)和竖线(|)的长度,如果仍需要更多信息或严格定义,请告诉我。
Bobas_Pett

@shooqie我删除了标签
Bobas_Pett

Answers:


5

Befunge,444个 368 323字节

&1>\1-:v
0v^*2\<_$00p>
_>:10p\:20pv^_@#-*2g00:+1,+55$
^!-<v*2g000<>$#<0>>-\:v
g2*^>>10g20g+v \ ^*84g_$:88+g,89+g,\1+:00
v#*!-1g02!g01_4^2_
>::00g2*-!\1-:10g-\20g-++>v
87+#^\#p01#<<v!`g01/2\+76:_
vv1-^#1-g01:\_$:2/20g`!
_ 2/^>:10g#vv#`g02/4*3:\+77
v>0p^^/2:/2_
<^2-1-g02</2`#*3:
0g+10p2*:^*3_1
! "#%$
%$"#!
 !!##%
|||_
 _ __

在线尝试!

绘制希尔伯特曲线的典型方法是沿着路径进行一系列的笔触和转弯,将结果渲染到位图或内存的某些区域中,然后在路径完成时将其渲染出来。当我们只有2000字节的内存要使用,并且其中包括程序本身的源代码时,这在Befunge中是不可行的。

因此,我们在此处采用的方法是提出一个公式,该公式可以告诉我们在给定的x,y坐标下确切输出哪个字符。要了解如何工作的,这是最容易忽略的ASCII渲染下手,只是觉得曲线作为由框字符起来:,和

当我们看到这样的曲线时,我们可以立即看到,右侧是左侧的精确镜像。可以通过在左侧查找其伙伴并在水平方向上进行反映来确定右侧的字符(即,出现的被交换,照原样和交换)。

3级希尔伯特曲线,显示垂直轴上的反射

然后看左下角,再次可以看到下半部分反映了上半部分。因此在底部的字符是简单地通过查找他们的伴侣的上方,并垂直反射它确定(即出现的被交换,因为是)。

3级希尔伯特曲线,显示了左下角在水平轴上的反射

这个角落的其余一半不太明显。右手块可以从与它对角相邻的块的垂直反射中得出。

3级希尔伯特曲线,显示如何得出左下角的右上角块

左手块可以从整个曲线最左上方的块的垂直反射中得出。

3级希尔伯特曲线,显示如何得出左下角的左上块

在这一点上,我们剩下的只是左上角,它只是另一个希尔伯特曲线,比其低一个迭代。从理论上讲,我们现在只需要再次重复该过程,但是有一点困难-在这个级别上,该块的左右两半并不是彼此完全相同的镜像。

因此,在除顶层以外的任何其他情况下,都需要将底角字符作为一种特殊情况进行处理,其中字符被反映为,而字符被反映为

3级希尔伯特曲线,显示如何得出左下角的左上块

但是除此之外,我们确实可以递归地重复此过程。在最后一层,我们将左上角的字符硬编码为,将其下面的字符硬编码为

图像序列,显示如何导出曲线的其余部分

现在我们有了确定特定x,y坐标处曲线形状的方法,如何将其转换为ASCII渲染?实际上,这只是一个简单的映射,它将每个可能的图块转换为两个ASCII字符。

  • 变为 _(空格加下划线)
  • 变成  (两个空格)
  • 变为|_(竖线加下划线)
  • 变为(竖线加空格)
  • 变为(再次用竖线加上空格)
  • 变成__(两个下划线)

这种映射起初并不直观,但是当您并排查看两个对应的渲染时,您可以看到它是如何工作的。

2级Hilbert曲线呈现为ASCII文字并带有方框字符

基本上就是全部。实际上,在Befunge中实现此算法是另一个问题,但是我将再次解释。


2

C,267字节

const n=4,s=1<<n,a[]={1,-s,-1,s};l,p,q;
t(d){d&=3;p-q||printf("%.2s",&"__|      _|       |___ _|_| | | "[l*8+d*2]);p+=a[l=d];}
h(d,r,n){n--&&(h(d+r,-r,n),t(d+r),h(d,r,n),t(d),h(d,r,n),t(d-r),h(d-r,-r,n));}
main(){for(;p=s*s-s,l=1,q<s*s;++q%s||putchar(10))h(0,1,n),t(3);}

在线尝试!

h()使用递归生成hlibert曲线的笔触。t()仅在笔位置p等于当前输出位置时打印笔画字符q

这效率低下但很简单。

如果曲线从左上角开始,则代码可以减少到256个字节。


建议puts("")而不是,putchar(10)"..."+l*8+d*2不是,&"..."[l*8+d*2]n--?h(d+r...-r,n):0不是n--&&(h(d+r...-r,n))
ceilingcat '18
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.