打印Cantor集


19

挑战

建立一个N级Cantor集

Cantor三元组是通过重复删除一组线段的中间三分之二来创建的。

程序接收一个参数N(整数),然后(以控制台或类似方式)打印N个康托集。印刷品只能包含非_下划线()和空格字符。参数可以是正数,也可以是负数,并且符号表示Cantor Set的构造方向:如果N > 0Cantor Set是向下构造的,并且N < 0Cantor Set是向上构造的。如果是N = 0这样,程序将打印一行(_)。

例如:

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

___________________________
_________         _________
___   ___         ___   ___
_ _   _ _         _ _   _ _

N = -3

_ _   _ _         _ _   _ _
___   ___         ___   ___
_________         _________
___________________________

获奖标准

因为这是一场高尔夫挑战赛的代码,所以最短的代码胜出。

编辑:根据ugoren的建议修改0输入。


当N = 0时为什么不打印任何内容?这使0成为一种特殊情况,并使使用递归变得更加困难。一般的处理方法是打印一张_(但是在获得-0时向下打印)。
ugoren 2012年

对。我已经修改了规格。
Averroes 2012年

Answers:


10

GolfScript,49 42 40个字符

~.abs.3\?'_'*\{.3%..,' '*\++}*](0>2*(%n*

感谢hammar 42-> 40。

可惜的是,我尝试采用更多数论方法的最佳尝试的时间更长:

~.abs:^3\?,{3^)?+3base(;1+1?.'_'*^@-)' '*+}%zip\0>2*(%n*

要么

~.abs 3\?:^,{6^*+3base.1+1?.('_'*@,@-' '*+}%zip\0>2*(%n*

我怀疑的长度basezip将使它不可能追上。


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*是39个字符,但在input上崩溃0。:-(
Ilmari Karonen

@IlmariKaronen,是的,被零除是为C实现我写的太痛苦,因为这意味着你不能n/abs(n)得到signum(n)
彼得·泰勒

6

Python中,116 113 104 103个字符

n=input()
d=n>0 or-1
for i in range(n*d+1)[::d]:
 s='_'*3**i
 while i<n*d:s+=len(s)*' '+s;i+=1
 print s

较旧的算法最多可包含113个字符

r=input()
u='_'
l=[u]
for _ in abs(r)*u:o=len(l[0]);l=[s+o*' '+s for s in l]+[u*o*3]
print'\n'.join(l[::r>0 or-1])

5

红宝石(97)

基于Steven Rumbalski的python版本:

n,r=$*[0].to_i,[?_]
n.abs.times{z=r[0].size;r=r.map{|s|s+' '*z+s}+[?_*z*3]}
puts n<0?r:r.reverse

先前的尝试,都相同的长度(112)

从零件构建线:

c=->x,n{n<1??_*x :(z=c[s=x/3,n-1])+' '*s+z}
r=(0..m=(n=$*[0].to_i).abs).map{|i|c[3**m,i]}
puts n<0?r.reverse: r

从一条线开始,在其中打孔:

r=[?_*3**a=(n=$*[0].to_i).abs]
a.times{|c|r<<r[-1].gsub((x=?_*o=3**(a-c-1))*3,x+' '*o+x)}
puts n<0?r.reverse: r


2

Common Lisp,217210个字符

(defun m(x)(flet((c(n v)(if(= n 0)`((,v))(cons(substitute v nil(make-list(expt 3 n)))(mapcar #'append(c(1- n)v)(c(1- n)" ")(c(1- n)v))))))(format t "~{~{~a~}~%~}"(let((r(c(abs x)'_)))(if(< x 1)(reverse r)r)))))

展开:

(defun m(x)
  (flet((c(n v)
    (if(= n 0)
       `((,v))
       (cons(substitute v nil(make-list(expt 3 n)))
            (mapcar #'append
                    (c(1- n)v)
                    (c(1- n)" ")
                    (c(1- n)v))))))
   (format t "~{~{~a~}~%~}"(let((r(c(abs x)'_)))(if(< x 1)(reverse r)r)))))

我认为Lisp代码是否能击败另一种语言的任何初始计数(C,219),我做的很好:)


2

C(163161个字符)

i,l,N;f(n,m,s){if(n){s=--n<l?m:s;f(n,m,s);f(n,s,s);f(n,m,s);}else
putchar(m);}main(n,v)int**v;{for(i=N=abs(n=atoi(1[v]));i+1;i--)l=n<N?N-i:i,f(N,95,32),f(0,10);}

ugoren的答案中借来了一些技巧,但核心逻辑却大不相同。我无法跟踪他的for循环,因此可能可以进行杂交并节省更多。


2

C,219 193 179 143 136 131个字符

遵循了Petyer Taylor的另一个想法,加上我自己的改进,又节省了6个。
集成了@PeterTaylor的一些技巧,并复制了他的主要功能,并做了一些细微的更改,从而节省了角色(复制它是否公平?因为我们俩人都不会赢得这个角色,所以我认为还算不错)。
我想到了递归的工作方式方面的重大改进,在看到Peter Taylor的回答后,我实现了它以重新获得领先。再次阅读他的答案时,我发现我几乎做到了他的所作所为。因此,这似乎是他建议的杂交。
还简化了循环main,保持了相同的长度。
并采取了彼得的把戏来打印换行符,而不是puts("")-保存一个字符。

int从变量声明中删除-警告,但节省4个字符。
新算法不会预先计算3 ^ x,而是使用单个循环打印3 ^ x字符。
可以通过定义保存更多内容int*v,但是64位将无法工作。
字符计数不包括空格(可以将其删除)。

o,i,n;
p(c) {
    n-- ?
        p(c),p(o>n?c:32),p(c)
    :
        putchar(c);
    n++;
}
main(c,v)int**v; {
    for(n=abs(c=atoi(v[1]));i<=n;i++)o=c+n?n-i:i,p(95),puts("");
}

较旧的算法,219个字符:

p(l,o,i,m,c,j) {
    for(;i<(m=l);i++)
        for(j=0,c=95;m/o||!putchar(c);j++)
            i/m%3-1||(c=32),m/=3;
    puts("");
}
main(c,v,n,i,l,o)int**v;{
    (n=atoi(v[1]))<0?n=-n:(c=0);
    for(i=n,l=1;i;i--)l*=3;
    o=c?1:l;
    for (;i<=n;i++)p(l,o,0),c?o*=3:(o/=3);
}

@PeterTaylor,我无法删除该i参数,因为使用全局变量会干扰mainl--会干扰o>=l,因此我必须将其替换为>(为什么我要把它写成一件坏事呢?)我也可以复制您main,它比我的要简单和短。
ugoren

@PeterTaylor,您说对了i-我错过了我真的不再使用它的事实(我想您是说我不通过它)。
ugoren

顺便说一句,我不介意您承担我的主要职责。我的经验法则是,复制他人的解决方案以更改单个角色过于激进,复制他人的解决方案以重写其中一半是完全公平的,并且两者之间有一个灰色区域。我们也许应该尝试就Meta达成一些社区标准。
彼得·泰勒

@PeterTaylor,我认为我们陷入了僵局。我的p现在看起来非常理想,而您的main表现更好(我不确定它是否理想,但是无法进一步提高)。因此,除了一个新颖的程序结构外,唯一的方法就是我们两个都复制另一个人的代码。
ugoren

顺便说一句,你如何计算你的角色?因为我让你最新版本的138个字符,而不是136
彼得·泰勒

2

J,44 39 38 37字节

' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|

使用迭代来构建初始以1(表示_)开头的下一组。

用法

   f =: ' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|
   f 0
_
   f 1
___
_ _
   f _1
_ _
___
   f 2
_________
___   ___
_ _   _ _
   f _2
_ _   _ _
___   ___
_________
   f 3
___________________________
_________         _________
___   ___         ___   ___
_ _   _ _         _ _   _ _
   f _3
_ _   _ _         _ _   _ _
___   ___         ___   ___
_________         _________
___________________________

说明

' _'{~0&>_&(]|.)(,:1)1&(,],.0&*,.])~|  Input: integer n
                                    |  Absolute value of n
                (,:1)                  The array [1]
                     1&(          )~   Repeat abs(n) times starting with x = [1]
                                 ]       Identity function, gets x
                            0&*          Multiply x by 0
                               ,.        Join the rows together
                         ]               Identity function, gets x
                          ,.             Join the rows together
                     1  ,                Prepend a row of 1's and return
      0&>                              Test if n is negative, 1 if true else 0
         _&(   )                       If n is negative
             |.                          Reverse the previous result
            ]                            Return that
                                       Else pass the previous result unmodified
' _'                                   The string ' _'
    {~                                 Select from the string using the result
                                       as indices and return

真好!我没有亲自尝试过,但我喜欢使用议程- @.也许与结合使用$:,在这里可能有用吗?例如(zero case)`(positive case)`(negative case)@.*,甚至可能":@_:`(positive case)`(|."1@$:)@.*
科纳·奥布莱恩

我没有尝试过递归解决方案,但可以尝试。
2016年

2

[R 141个139 137字节

m=abs(n<-scan());write("if"(n<m,rev,c)(c(" ","_")[Reduce(`%x%`,rep(list(matrix(c(1,1,1,1,0,1),3)),m),t(1))[,1+2^m-2^(m:0)]+1]),1,3^m,,"")

在线尝试!

-15个字节,也感谢Giuseppe '('用作身份功能;write而不是cat打印输出;聪明地使用%x%

感谢Kirill L.将-2个字节使用c而不是'('用作标识函数。


Kronecker产品可以在这里工作吗?%x%?交替排列可能会有一些问题……
朱塞佩

我尝试过@Giuseppe,在您的“从较小的“ H” s答案中创建“ H”的基础上...我会再尝试一次。
JayCe

啊,所以是你赞成的。那也是我想到的唯一原因kron!我以为如果找到正确的方法,应该可以减少到125个字节。
朱塞佩

您可以将其`(`用作身份功能,因此可以write直接使用cat和而不是for循环。141字节
朱塞佩

@Giuseppe我不知道(可以用这种方式,if 也可以用来从两个函数中选择。我将开始使用write ...会节省很多“ \ n”。
JayCe

1

Python,177164个字符

N=input()
n=abs(N)
c=lambda x:0if x<1 else x%3==1or c(x/3)
r=["".join([["_"," "][c(x/3**i)]for x in range(3**n)])for i in range(n+1)]
print"\n".join(r[::N>0 or-1])

由于您使用的是Python 2,因此无需强制转换inputas 的结果int。您的后两行可能会缩短为print"\n".join(r[::N>0 or-1])
Steven Rumbalski'2

@Steven我进行了更改。谢谢。
2012年

1

Perl,113个字符

$i=abs($I=<>);@w=$_='_'x3**$i;while($i--){$x=3**$i;s/(__){$x}/'_'x$x.' 'x$x/eg;push@w,$_}say for$I>0?reverse@w:@w

展开:

$i=abs($I=<>);
@w=$_='_'x3**$i;
while($i--){
    $x=3**$i;
    s/(__){$x}/'_'x$x.' 'x$x/eg;
    push@w,$_
}
say for$I>0?reverse@w:@w

1

JavaScript 121字节

内部递归函数,然后根据需要处理向后输出

n=>(f=(n,t=n&&f(n-1),r=t[0])=>n?[r+r+r,...t.map(x=>x+t[n]+x)]:['_',' '],f=f(n<0?-n:n),f.pop(),n<0?f.reverse():f).join`\n`

少打高尔夫球

n=>{
  var f = n => { // recursive function
    var t = n && f(n-1), r = t[0]
    return n 
      ? [r+r+r, ...t.map(x => x+t[n]+x)]
      : ['_',' ']
  };
  f = f(n < 0 ? -n : n);
  f.pop(); // last row is all blanks
  if (n<0) f.reverse();
  return f.join`\n`
}

测试

var F=
n=>(f=(n,t=n&&f(n-1),r=t[0])=>n?[r+r+r,...t.map(x=>x+t[n]+x)]:['_',' '],f=f(n<0?-n:n),f.pop(),n<0?f.reverse():f).join`\n`

function go()
{
  var n=+I.value
  O.textContent = F(n)
}

go()
<input id=I type=number value=3 oninput='go()'>
<pre id=O></pre>


1

分批,265个 262 242 236 235字节

@echo off
set/pn=
set c=%n%,-1,0
if %n% lss 0 set c=0,1,%n:-=%
for /l %%i in (%c%)do call:l %%i
exit/b
:l
set s=_
for /l %%j in (1,1,%n:-=%)do call:m %1 %%j
echo %s%
:m
set t=%s%
if %1 lss +%2 set t=%s:_= %
set s=%s%%t%%s%

编辑:由于@ l4m2,节省了12个 19字节。通过删除不必要的%a%变量节省了8个字节。


是247个字节。
科纳·奥布莱恩

@ ConorO'Brien请注意,如果我计算所有CR和LF(我确定您不需要这样做,但我很懒,那将是261)。
尼尔

因此,您不是要从代码中删除CR吗?即使.BAT文件不需要它,SE也剥离了它?:P
Conor O'Brien

@ ConorO'Brien我接受使用记事本编写批处理文件的惩罚。
尼尔

你可以做类似的事情set c=%n%,-1,0 [LF] if %n% lss 0 set c=0,1,%a% [LF] for /l %%i in (%c%)do call:l %%i吗?
l4m2



0

序言(SWI) 265个 232 213字节

S-E-R:-between(S,E,R).
[]/R/R.
[H|T]/B/R:-T/[H,32,H|B]/R.
N+R:-(N>0->O is N-1,O+S,S/[]/R;R=`_`).
N*[H|T]:-1-N-_,writef("%n",[H]);N*T.
_*[]:-nl.
-N:-(0-N-J,K is N-J;N-0-I,J is -I,K is I-N),L is 3^K,J+R,L*R,1=0;1=1.

在线尝试!


0

PowerShell,111字节

filter f{if($s=[math]::Sign($_)){($x=$_-$s|f|%{$_+' '*($l=$_|% Le*)+$_})|?{$s-1};'_'*3*$l;$x|?{$s+1}}else{'_'}}

在线尝试!

少打高尔夫球:

filter f{
    if($sign=[math]::Sign($_)){
        $x=$_-$sign|f|%{
            $_+' '*($length=$_|% Length)+$_
        }
        $x|?{$sign-1}  # output $x if $_ is negative
        '_'*3*$length
        $x|?{$sign+1}  # output $x if $_ is positive
    }
    else{
        '_'
    }
}
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.