Cantor Seti Yazdır


19

Meydan okuma

N Düzeyinde Cantor Seti oluşturun .

Cantor üçlü kümesi, bir dizi çizgi parçasının açık orta üçte birini tekrar tekrar silerek oluşturulur.

Program bir parametre N(bir tamsayı numarası) alır ve daha sonra (konsolda veya benzer şekilde) bir Cantor N kümesi seviyesi yazdırır. Baskı yalnızca alt çizgi ( _) ve boşluk karakterleri içerebilir . Parametre pozitif veya negatif olabilir ve işareti Cantor Set konstrüksiyon yönelimini gösterir: N > 0Cantor Set aşağı doğru inşa edilmişse N < 0ve Cantor Set yukarı doğru inşa edilmişse . Eğer N = 0daha sonra program tek bir çizgi basar ( _).

Örneğin:

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

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

N = -3

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

Kazanma kriterleri

Bir kod golf meydan okuma olduğu için, en kısa kod kazanır.

Düzenlendi: 0 girdisini ugoren'in önerisiyle değiştirin.


N = 0 olduğunda neden hiçbir şey yazdırmıyor? Bu 0'ı özel bir durum haline getirir ve özyinelemeyi kullanmayı zorlaştırır. Genel işlem tek bir baskı yapmak _(ancak -0 alırken aşağı doğru yazdırmak) olacaktır.
ugoren

Sağ. Teknik özellikleri zaten değiştirdim.
Averroes

Yanıtlar:


10

GolfScript, 49 42 40 karakter

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

42-> 40 kişilik hamam sayesinde .

Henüz daha fazla teorik bir yaklaşım benim en iyi girişimim ne yazık ki çok daha uzun:

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

veya

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

ve ben uzunluğuna şüpheli baseve zipimkansız yakalamak için yapacaktır.


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*39 karakterdir, ancak girdide kilitlenir 0. :-(
Ilmari Karonen

@IlmariKaronen, evet, sıfıra bölme de yazdığım C uygulaması için bir acıydı, çünkü bu n/abs(n)elde edemeyeceğiniz anlamına geliyordu signum(n).
Peter Taylor

6

Python, 116 113 104 103 karakter

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

Eski algoritma 113 karakterle dolduruldu

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

Yakut (97)

Steven Rumbalski'nin python versiyonuna dayanarak:

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

Önceki denemeler, her ikisi de aynı uzunlukta (112)

Parçalardan çizgiler oluşturun:

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

Bir satırla başlayın, içinde delikler açın:

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

Ortak Lisp, 217 210 karakter

(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)))))

Expanded:

(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 kod başka bir dil (C, 219) için herhangi bir ilk sayımı yenmek için yönetir eğer anlıyorum :)


2

C ( 163161 karakter)

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);}

Uugoren'in cevabından birkaç püf noktası ödünç alır , ancak çekirdek mantık oldukça farklıdır. Onun döngüsünü takip edemedim, bu yüzden birkaç tane daha hibridize etmek ve kaydetmek mümkün olabilir.


2

Cı, 219 193 179 143 136 131 karakter

Petyer Taylor'ın fikirlerinden bir diğerini ve kendiminkini geliştirerek 6 tane daha kaydettik.
@PeterTaylor'dan bazı ipuçları entegre etti, ayrıca ana işlevini, bir karakteri koruyan küçük değişiklikler ile kopyaladı (kopyalamak adil mi?
Özyinelememin işleyişinde önemli bir gelişme düşündüm ve Peter Taylor'ın cevabını gördükten sonra, ipucunu yeniden kazanmak için uyguladım. Cevabını tekrar okurken neredeyse tam olarak ne yaptığını gördüm. Bu, onun önerdiği hibridizasyon gibi görünüyor.
Ayrıca main, aynı uzunluğu koruyarak döngüyü basitleştirdi .
Ve Peter'ın yeni satır basma hilesini aldı, yerine puts("")- bir karakter kaydeder.

intDeğişken bildirimden kaldırıldı - bir uyarı, ancak 4 karakter kaydeder.
Yeni algoritma önceden 3 ^ x hesaplamaz, ancak 3 ^ x karakteri yazdırmak için tek bir döngü kullanır.
Tanımlayarak bir tane daha kaydedebilir int*v, ancak 64bit çalışmaz.
Karakter sayısı boşlukları (kaldırılabilen) hariç tutar.

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("");
}

Eski algoritma, 219 karakter:

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, iparametrenin kaldırılması mümkün değil , çünkü global kullanımı engelleyebilir main. l--müdahale edecek o>=lve onunla değiştirmek zorunda kalacağım >(neden kötü bir şeymiş gibi yazıyorum?) Sizi de kopyalayabilirim main, ki bu benimkinden daha basit ve kısadır.
ugoren

@PeterTaylor, haklıydın i- gerçekten artık kullanmadığım gerçeğini kaçırdım (geçmediğimi düşündüğünü sanıyordum).
ugoren

Bu arada, ana işlevimi almana aldırmam. Temel kuralım, tek bir karakteri değiştirmek için bir başkasının çözümünü kopyalamanın aşırı agresif olması, bir başkasının çözümünün yarısını yeniden yazmak için kopyalamak son derece adil ve aralarında bir yerde gri bir alan var. Belki de meta konusunda bazı topluluk standartlarını kabul etmeye çalışmalıyız.
Peter Taylor

@PeterTaylor, sanırım bir çeşit çıkmaza ulaştık. Benim pşimdi oldukça optimal görünüyor ve maindaha iyiydi (optimal olduğundan emin değilim, ancak daha fazla geliştiremiyorum). Bu yüzden yeni dahiyane bir program yapısı dışında, gidilecek tek yol ikimizden birinin kodunu kopyalamaktı.
ugoren

BTW Karakterlerinizi nasıl sayıyorsunuz? Çünkü 136 değil en son 138 karakterinizi yapıyorum.
Peter Taylor

2

J, 44 39 38 37 bayt

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

Başlangıçta 1 (temsil eden _) ile başlayarak sonraki seti oluşturmak için yinelemeyi kullanır .

kullanım

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

açıklama

' _'{~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

Güzel! Kişisel olarak denemedim, ama gündemi kullanmayı seviyorum - belki de bununla @.birlikte $:, burada bir işe yarayabilir mi? Örneğin (zero case)`(positive case)`(negative case)@.*, hatta belki de bir şey ":@_:`(positive case)`(|."1@$:)@.*.
Conor O'Brien

Özyinelemeli bir çözüm denemedim, ama deneyebilirim.
mil

2

R , 141139133 bayt

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,,"")

Çevrimiçi deneyin!

-15 bayt teşekkürler Giuseppe'nin '('kimlik fonksiyonu olarak kullanması ; çıktı yazdırmak writeyerine cat; akıllı kullanımı %x%.

Kimlik fonksiyonu cyerine kullanarak Kirill L. sayesinde -2 bayt '('.


Kronecker ürünü burada çalışabilir mi? %x%? Belki de alternatif satırlar almakla ilgili bazı sorunlar olabilir ...
Giuseppe

@Giuseppe "Daha küçük" H "s" yanıtından bir "H" oluşturun. "
JayCe

Ah, bunu onaylayan sensin. Ben de öyle düşünmüştüm kron! Doğru yaklaşımı bulabilirsek, bunun 125 bayta inebilmesi gerektiğini düşünürdüm.
Giuseppe

`(`kimlik işlevi olarak kullanabilirsiniz , böylece bir döngü writeyerine doğrudan kullanabilirsiniz . 141 baytcatfor
Giuseppe

@Giuseppe (Bu şekilde kullanılabileceğine dair hiçbir fikrim yoktu ya da bu if iki işlev arasından seçim yapmak için kullanılabilir. Ve write kullanmaya başlayacağım ... çok fazla "\ n" kaydeder.
JayCe

1

Python, 177 164 karakter

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 kullandığınız için inputas sonuçlarını kullanmanıza gerek yoktur int. Son iki hattınız kısaltılabilirprint"\n".join(r[::N>0 or-1])
Steven Rumbalski

@Steven değişiklikler yaptım. Teşekkür ederim.
Ante

1

Perl, 113 karakter

$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

Expanded:

$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 bayt

İç özyinelemeli işlev, daha sonra gerekirse geri çıkışa dikkat edin

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`

Daha az golf

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`
}

Ölçek

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

Toplu, 265 262 242 236 235 bayt

@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%

Düzenleme: @ l4m2 sayesinde 12 19 bayt kaydedildi. Gereksiz %a%değişken kaldırılarak 8 bayt kaydedildi .


Bu 247 bayt için.
Conor O'Brien

@ ConorO'Brien Tüm CR'lerin yanı sıra LF'leri saydığımda 261 olacağını unutmayın (ki bunu yapmanız gerekmediğinden eminim ama tembelim).
Neil

Yani CR'leri kodunuzdan kaldırmıyor musunuz? Rağmen .BAT dosyaları tarafından gerekli ve SE tarafından yine de soyulmuş? : P
Conor O'Brien

@ ConorO'Brien Toplu İş dosyaları yazmak için Not Defteri'ni kullanmayı kabul ettiğim bir ceza.
Neil

Gibi bir şey yapabilir misin 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

Prolog (SWI) , 265 232 213 bayt

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.

Çevrimiçi deneyin!


0

PowerShell , 111 bayt

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

Çevrimiçi deneyin!

Daha az golf:

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{
        '_'
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.