캔터 세트 인쇄


19

도전

N 레벨 Cantor 세트 만들기 .

Cantor 3 진 세트는 라인 세그먼트 세트의 열린 중간 1/3을 반복적으로 삭제하여 작성됩니다.

프로그램은 하나의 매개 변수 N(정수 )를 수신 한 다음 N 레벨의 Cantor Set을 콘솔 (또는 유사한 방식으로) 인쇄합니다. 인쇄물에는 밑줄 ( _)과 공백 문자 만 사용할 수 있습니다 . 매개 변수는 양수 또는 음수 일 수 있으며 기호는 Cantor Set 구성 방향을 나타냅니다 N > 0. Cantor Set이 아래쪽으로 구성 N < 0되고 Cantor Set가 위쪽으로 구성되어있는 경우 . 그렇다면 N = 0프로그램은 한 줄 ( _)을 인쇄합니다 .

예를 들면 다음과 같습니다.

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

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

N = -3

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

우승 기준

코드 골프 챌린지이므로 가장 짧은 코드가 승리합니다.

편집 : ugoren의 제안으로 0 입력을 수정하십시오.


N = 0 일 때 왜 아무것도 인쇄하지 않습니까? 이것은 0을 특별한 경우로 만들고 재귀를 사용하기 어렵게 만듭니다. 일반적인 처리 방법은 하나를 인쇄하는 것입니다 _(그러나 -0을 얻으면 아래쪽으로 인쇄).
ugoren

권리. 사양을 이미 수정했습니다.
Averroes

답변:


10

GolfScript, 49 42 40 자

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

42-> 40의 hammar 덕분에 .

더 많은 수의 이론적 접근법에 대한 나의 최선의 시도는 슬프게도 훨씬 길다.

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

또는

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

나는 길이 것으로 생각 base하고 zip불가능 잡을 수 있도록 할 것이다.


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*39 자이지만 입력시 충돌합니다 0. :-(
Ilmari Karonen

당신이 할 수없는 것을 의미하기 때문에 @IlmariKaronen는, 그래, 0으로 나누기, 나는 너무 쓴 C 구현을위한 고통이었다 n/abs(n)얻을 signum(n).
피터 테일러

6

파이썬 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

3

펄, 93 자

@x=($t=$x=_ x 3**($a=abs($n=<>)),map$x.=$"x($x=~s/(.)../$1/g).$x,1..$a);say for$n<0?sort@x:@x

Peter Taylor의 GolfScript 솔루션 이 Perl로 얼마나 잘 전달되는지 확인하려고 생각했습니다 . 주목할만한 기능은 공백이 전에 정렬된다는 사실을 사용하여 세 개의 문자를 저장 하는 sort대신 사용하는 것입니다 .reverse_


2

공통 리스프, 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동일한 길이를 유지하면서 루프 인을 단순화했습니다 .
그리고 Peter의 속임수를 사용하여 개행 문자를 인쇄하는 대신 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전역을 사용 하면가 방해하기 때문에 매개 변수를 제거 할 수 없습니다 main. l--를 방해하고 o>=l그것을 대체해야합니다 >(왜 나쁜 것 인 것처럼 작성해야합니까?). 나는 또한 당신 main보다 더 간단하고 짧습니다.
ugoren

@ PeterTaylor, 당신이 옳았 i습니다-나는 더 이상 그것을 사용하지 않는다는 사실을 놓쳤습니다.
ugoren

그건 그렇고, 나는 당신이 내 주요 기능을 취하는 것을 신경 쓰지 않습니다. 제 경험에 따르면 다른 사람의 단일 문자 변경 솔루션을 복사하는 것은 지나치게 공격적이며 다른 사람의 솔루션을 복사하여 절반을 다시 작성하는 것은 완전히 공평하며 중간에 회색 영역이 있습니다. 메타에 대한 일부 커뮤니티 표준에 동의하려고 노력해야합니다.
피터 테일러

@ PeterTaylor, 우리는 일종의 교착 상태에 도달했다고 생각합니다. 나는 p지금 매우 최적 인 것처럼 보이고 당신 main은 더 나았습니다 (최적인지 확실하지 않지만 더 향상시킬 수는 없습니다). 따라서 새로운 독창적 인 프로그램 구조를 제외하고 갈 수있는 유일한 방법은 상대방의 코드를 복사하는 것입니다.
ugoren

BTW 캐릭터를 어떻게 세고 있습니까? 나는 최신 버전을 136 문자가 아닌 138 문자로 만들었 기 때문에.
Peter Taylor

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

좋은! 나는 개인적으로 시도하지 않은,하지만 난 의제를 사용하여 사랑 @.이와 결합 --perhaps $:, 여기에 몇 가지 사용이 될 수 있을까? 예를 들면 같은 (zero case)`(positive case)`(negative case)@.*심지어 어쩌면, 또는 ":@_:`(positive case)`(|."1@$:)@.*.
코너 O'Brien

재귀 솔루션을 시도하지 않았지만 시도해 볼 수 있습니다.
마일

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의 '('identity 함수로도 사용할 수 있습니다. 출력을 인쇄하는 write대신 cat; 의 영리한 사용 %x%.

Kirill L. 덕분에 식별 기능 c대신 -2 바이트 사용 '('.


크로네 커 제품이 여기서 작동합니까? %x%? 아마도 행을 번갈아가는 데 문제가있을 수 있습니다.
Giuseppe

@Giuseppe 나는 "작은"H "답변에서"H "를 작성하려고 시도했습니다 ... 다시 시도하겠습니다.
JayCe

아, 그래서 당신은 그것을 찬성했습니다. 그것이 내가 생각한 유일한 이유입니다 kron! 올바른 접근 방법을 찾을 수 있다면 이것이 125 바이트로 내려갈 수 있다고 생각합니다.
주세페

당신이 사용할 수있는 `(`당신이 사용할 수 있도록 신원 함수로 write대신 직접 cat하고 for루프. 141 바이트
주세페

@ 주세페 나는 (이런 식 if 으로 사용될 수 있거나 두 가지 기능 중에서 선택 하는 데 사용될 수 있다고 생각하지 못했습니다 . 그리고 쓰기 사용을 시작하겠습니다 ... 많은 "\ n"을 저장합니다.
JayCe

1

Python, 177 164 자

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

@Steven 나는 변경했다. 감사합니다.
Ante

1

펄, 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

자바 스크립트 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 LF뿐만 아니라 모든 CR을 세면 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

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{
        '_'
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.