使用斜线绘制希尔伯特曲线


30

希尔伯特曲线是可以被表示为空间填充的分形Lindenmayer系统与连续世代看起来像这样:
希尔伯特曲线
由于http://www.texample.net/tikz/examples/hilbert-curve/用于图像。

目标

编写尽可能短的程序(以字节为单位),该程序从stdin取一个正整数n并仅使用正斜杠,反斜杠,空格和换行符将n阶Hilbert曲线绘制到stdout。

例如,如果输入是1输出,则必须为

 \
\/

如果输入是2输出,则必须为

  /
  \/\
/\   \
 / /\/
 \ \
  \/

如果输入是3输出,则必须为

       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/

等等。(如果将它们粘贴到行间距较小的东西中,它们看起来会更好。)

输出中不应在曲线的端点上方或下方包含换行符,也不应在任何直线上包含任何尾随空格。

Answers:


10

Ruby,247230205 字符

r=?D
y=d=0
z=(1..2*x=2**gets.to_i.times{r.gsub!(/\w/){$&<?H?'-H~+D~D+~H-':'+D~-H~H-~D+'}}-1).map{' '*2*x}
r.bytes{|c|c>99?(z[y-=s=-~d/2%2][x-=1-d/2]='/\\'[d%2]
x+=d/2
y+=1-s):d-=c
d%=4}
puts z.map &:rstrip

使用Lindenmayer表示形式的ASCII-turtle方法(在此处尝试)。

非常感谢@Ventero进行了更多高尔夫活动。


Golfed更多这一点,希望你不要介意:ideone.com/kvcPWT -将.map(&:rstrip)不得不加入到履行“没有尾随空格”的要求。
Ventero 2014年

@Ventero谢谢。希望您不要介意我接受了您的解决方案-您甚至可能会舍弃map参数周围的括号。
霍华德

啊,当然!我也只是意识到这是可能的内联的定义x,并缩短分配yd,总共205个字符(见在同一条链路前)。
Ventero 2014年

12

巨蟒,282

from numpy import*
def r(n):
 x=2**n-2;b=3*x/2+1;c=x/2+1;a=zeros((x*2+2,)*2,int);a[x+1,x+1]=1;a[b,x/2]=a[x/2,b]=-1
 if n>1:s=r(n-1);a[:x,c:b]=rot90(s,3)*-1;a[c:b,:x]|=rot90(s)*-1;a[c:b,x+2:]|=s;a[x+2:,c:b]|=s
 return a
for l in r(input()):print''.join(' /\\'[c] for c in l).rstrip()

这使用递归方法从前一条曲线中构造出n阶希尔伯特曲线。曲线以2d numpy数组表示,以便更好地切片和处理。

这里有些例子:

$ python hilbert.py
2
  /
  \/\
/\   \
 / /\/
 \ \
  \/
$ python hilbert.py
3
       \
     /\/
    /   /\
    \/\ \ \
  /\  / / /
 / /  \/  \/\
 \ \/\  /\   \
\/   / / / /\/
  /\/ /  \ \
  \   \/\ \/
   \/\   \
     / /\/
     \ \
      \/
$ python hilbert.py
4
              /
              \/\
            /\   \
           / / /\/
           \ \ \  /\
         /\/  \/  \ \
        /   /\  /\/ /
        \/\ \ \ \   \/\
      /\  / /  \ \/\   \
     / /  \/ /\/   / /\/
     \ \/\  /   /\/ /   /\
   /\/   /  \/\ \   \/\ \ \
  /   /\/ /\  / / /\  / / /
  \/\ \  / /  \/ / /  \/  \/\
/\   \ \ \ \/\   \ \/\  /\   \
 / /\/  \/   / /\/   / / / /\/
 \ \  /\  /\/  \  /\/ /  \ \
  \/  \ \ \  /\/  \   \/\ \/
    /\/ / / /   /\ \/\   \
    \   \/  \/\ \ \  / /\/
     \/\  /\  / / /  \ \
       / / /  \/  \/\ \/
       \ \ \/\  /\   \
        \/   / / / /\/
          /\/ /  \ \
          \   \/\ \/
           \/\   \
             / /\/
             \ \
              \/

5

Malsys - 234 221个字符

我在这里闻到一些L系统的信息:) Malsys是在线L系统解释器。这并不是很认真的入门,但是我觉得这种解决方案有些有趣。

Malsys的语法实际上并不适合打高尔夫球,因为它包含许多冗长的关键字,但它仍然很短,可读性和表达力强。

lsystem HilbertCurveAscii {
    set symbols axiom = R;
    set iterations = 5;
    set rightAngleSlashMode = true;
    interpret F as DrawLine;
    interpret + as TurnLeft;
    interpret - as TurnRight;
    rewrite L to + R F - L F L - F R +;
    rewrite R to - L F + R F R + F L -;
}
process all with HexAsciiRenderer;

http://malsys.cz/g/3DcVFMWn

口译员:http : //malsys.cz/Process

高尔夫球版:

lsystem H{set symbols axiom=R;set iterations=3;set
rightAngleSlashMode=1;interpret.as DrawLine;interpret+as
TurnLeft;interpret-as TurnRight;rewrite L to+R.-L.L-.R+;rewrite
R to-L.+R.R+.L-;}process H with HexAsciiRenderer;

那么,Ascii六角六角曲线呢?:)

      ____
 ____ \__ \
 \__ \__/ / __
 __/ ____ \ \ \
/ __ \__ \ \/
\ \ \__/ / __
 \/ ____ \/ /
    \__ \__/
    __/

http://malsys.cz/g/ae5v5vGB


2

JavaScript的(ES6)313 340

编辑使用 某些不良做法删除的某些字符-例如全局变量w而不是函数H的返回值

将每个x,y的x,y位置转换为距离d(请参阅Wikipedia),并验证是否连接了最近的位置,

在FireFox控制台中进行测试。通过弹出窗口输入,通过console.log输出。

图像上方或下方没有尾随空格,也没有换行符。但是每行都以换行符结尾,我认为这是制作Ascii艺术图像的正确方法。

n=1<<prompt(),d=n-1
H=(s,x,y)=>{for(w=0;s>>=1;)p=x&s,q=y&s,w+=s*s*(3*!!p^!!q),q||(p&&(x=s-1-x,y=s-1-y),[x,y]=[y,x])}
for(r=t='';++r<d+n;t+='\n')for(r>d?(x=r-d,f=x-1):(f=d-r,x=0),t+=' '.repeat(f),z=r-x;x<=z;)
h=H(n,y=r-x,x)|w,H(n,y,x-1),x?t+=' \\'[h-w<2&w-h<2]:0,H(n,y-1,x++),y?t+=' /'[h-w<2&w-h<2]:0
console.log(t)

您可以使用alert代替来保存一些字符console.logfor第四行的后面还有一个多余的空间,您应该可以摆脱最后的换行符。
鲍勃

@Bob是的,事实上我可以再保存15个字符,但我还是放弃了查看超过300个字符的信息。我不喜欢使用“警报”,因为如果没有固定间距的字体,图像将完全无法识别
edc65

2

Perl,270个字符

超级高尔夫

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;eval's/A|B/$d{$&}/g;'x$n;s/A|B//g;map{if(/F/){if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}$s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]}else{($r+=2*/-/-1)%=4}}/./g;map{print map{$_||$"}@$_,$/}@s

没有那么多打高尔夫球

$_=A,%d=<A -BF+AFA+FB- B +AF-BFB-FA+>,$x=2**($n=<>)-2;
eval's/A|B/$d{$&}/g;'x$n;
s/A|B//g;
map{if(/F/){
    if($r+$p==3){$y+=$p<=>$r}else{$x+=$r<2?$r-$p:$p-$r}
        $s[($r-1)%4>1?$x--:$x++][$r>1?$y--:$y++]=qw(/ \\)[($p=$r)%2]
    }else{
        ($r+=2*/-/-1)%=4
    }
}/./g;
map{print map{$_||$"}@$_,$/}@s

如果我对Perl有了更好的了解,可能会进一步打下去。使用Lindenmayer系统方法,使用第1行中定义的生产规则。


2

APL(Dyalog Unicode),90字节SBCS

⎕∘←¨' +$'r''¨↓1↓∘⍉∘⌽⍣4' /\'[{3|(⊢+⍉)2@(¯1 0+3 1×s÷2)s⊢(¯.5×≢⍵)⊖(2×s←⍴⍵)↑⍵,⍨-⊖⍵}⍣⎕⊢2 2⍴0]

在线尝试!

2 2⍴0 零的2x2矩阵

{ }⍣⎕ 输入N并应用N次函数

⍵,⍨-⊖⍵ 将矩阵的垂直反转和取反的副本连接到矩阵的左侧

(2×s←⍴⍵)↑用零填充,以使尺寸(记住为s)是参数的两倍

¯.5×≢⍵ 向下旋转以便将其垂直居中,并夹在填充零点之间

2@(¯1 0+3 1×s÷2) 将2-s放在特定位置-这些是分形的较小实例之间的链接斜线

(⊢+⍉) 将矩阵及其转置后的自我相加

3|模3; 我们使用了否定,因此请注意-1≡2(mod 3)和-2≡1(mod 3)

' /\'[ ] 使用矩阵元素作为字符串中的索引 ' /\'

1↓∘⍉∘⌽⍣4 从所有侧面修剪1元素宽的空白边距

分成几行

' +$'⎕r''¨ 从每个空格中删除尾部空格(此挑战是必需的)

⎕∘←¨ 输出每个

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.