Cantor-Set drucken


19

Die Herausforderung

Erstellen Sie ein Cantor-Set mit N-Level .

Die ternäre Cantor-Menge wird durch wiederholtes Löschen des offenen mittleren Drittels einer Menge von Liniensegmenten erstellt.

Das Programm empfängt einen Parameter N(eine Ganzzahl) und druckt dann (auf Konsolen- oder ähnliche Weise) einen Cantor-Satz von N Ebenen. Der Ausdruck darf nur nicht mit einem Punkt ( _) und mit Leerzeichen versehene Zeichen enthalten. Der Parameter kann positiv oder negativ sein und das Vorzeichen gibt die Konstruktionsausrichtung des Cantor-Sets an: Wenn N > 0das Cantor-Set nach unten und N < 0das Cantor-Set nach oben konstruiert ist. Wenn N = 0dann druckt das Programm eine einzelne Zeile ( _).

Beispielsweise:

N = 2

_________
___   ___
_ _   _ _

N = -2

_ _   _ _
___   ___
_________

N = 3

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

N = -3

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

Gewinnkriterien

Da es sich um eine Code-Golf-Herausforderung handelt, gewinnt der kürzeste Code.

Bearbeitet: Ändere die Eingabe von 0 nach dem Vorschlag von ugoren.


Warum nichts drucken, wenn N = 0? Dies macht 0 zu einem Sonderfall und erschwert die Verwendung der Rekursion. Die allgemeine Vorgehensweise wäre, eine einzelne zu drucken _(aber sie nach unten zu drucken, wenn Sie -0 erhalten).
Ugoren

Recht. Ich habe die Spezifikationen bereits geändert.
Averroes

Antworten:


10

GolfScript, 49 42 40 Zeichen

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

Mit Dankeschön an Hammar für 42-> 40.

Mein bisher bester Versuch einer zahlen-theoretischen Herangehensweise ist leider viel länger:

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

oder

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

und ich vermute, dass die Länge von baseund zipes unmöglich machen wird, aufzuholen.


~.abs.@/\.3\?'_'*\{.3%..,' '*\++}*](%n*beträgt 39 Zeichen, stürzt jedoch bei der Eingabe ab 0. :-(
Ilmari Karonen

@IlmariKaronen, ja, das Teilen durch Null war für die C-Implementierung, die ich auch geschrieben habe, ein Schmerz, weil es bedeutete, dass man nichts tun kann n/abs(n), um es zu bekommen signum(n).
Peter Taylor

6

Python, 116 113 104 103 Zeichen

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

Älterer Algorithmus mit 113 Zeichen aufgefüllt

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

Rubin (97)

Basierend auf Steven Rumbalskis Python-Version:

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

Frühere Versuche, beide gleich lang (112)

Bauen Sie Linien aus Teilen:

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

Beginnen Sie mit einer Linie und bohren Sie Löcher hinein:

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

Perl, 93 Zeichen

@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

Ich dachte, ich würde versuchen zu sehen, wie gut sich Peter Taylors GolfScript-Lösung auf Perl portieren lässt. Zu den bemerkenswerten Merkmalen gehört die Verwendung von sortanstelle von reverse, um drei Zeichen zu speichern, wobei die Tatsache genutzt wird, dass ein Leerzeichen zuvor sortiert wurde _.


2

Common Lisp, 217 210 Zeichen

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

Erweitert:

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

Ich denke, wenn der Lisp-Code eine Anfangszählung für eine andere Sprache übertrifft (C, 219), geht es mir gut :)


2

C ( 163 161 Zeichen)

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

Leiht sich ein paar Tricks aus Ugorens Antwort , aber die Kernlogik ist ganz anders. Ich konnte seiner for-Schleife nicht folgen, daher ist es möglicherweise möglich, weitere zu hybridisieren und zu speichern.


2

C, 219 193 179 143 136 131 Zeichen

Befolgte eine andere Idee von Petyer Taylor und eine Verbesserung meiner eigenen, sparte 6 weitere.
Einige Tipps von @PeterTaylor wurden integriert und seine Hauptfunktion mit geringfügigen Änderungen kopiert, die einen Charakter retten (ist es fair, ihn zu kopieren? Da keiner von uns diesen gewinnen wird, denke ich, dass es nicht so schlimm ist).
Ich dachte an eine signifikante Verbesserung der Funktionsweise meiner Rekursion und nachdem ich die Antwort von Peter Taylor gesehen hatte, implementierte ich sie, um den Vorsprung wiederzugewinnen. Als ich seine Antwort noch einmal las, sah ich, dass ich fast genau das tat, was er tat. Das scheint also die von ihm vorgeschlagene Hybridisierung zu sein.
Vereinfachte auch das Einschleifen bei maingleicher Länge.
Und nahm Peters Trick, um eine neue Zeile zu drucken, anstatt puts("")- einen Charakter zu speichern.

Aus intVariablendeklaration entfernt - eine Warnung, spart jedoch 4 Zeichen.
Der neue Algorithmus berechnet nicht 3 ^ x im Voraus, sondern verwendet eine einzelne Schleife, um 3 ^ x Zeichen zu drucken.
Kann durch Definieren einen weiteren speichern int*v, aber dann funktionieren 64-Bit nicht.
Die Anzahl der Zeichen schließt Leerzeichen aus (diese können entfernt werden).

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

Älterer Algorithmus, 219 Zeichen:

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, ich kann den iParameter nicht entfernen , da die Verwendung der globalen würde stören main. l--wird stören o>=l, und ich muss es ersetzen >(warum schreibe ich es dann so, als wäre es eine schlechte Sache?) Ich könnte dich auch kopieren main, was einfacher und kürzer ist als meine.
Ugoren

@PeterTaylor, du hattest Recht i- ich habe die Tatsache übersehen, dass ich es wirklich nicht mehr benutze (ich dachte, du meinst, ich übergebe es nicht).
Ugoren

Übrigens macht es mir nichts aus, dass Sie meine Hauptfunktion übernehmen. Meine Faustregel ist, dass das Kopieren der Lösung eines anderen zum Ändern eines einzelnen Zeichens übermäßig aggressiv ist, das Kopieren der Lösung eines anderen zum Umschreiben der Hälfte davon ist vollkommen fair, und irgendwo dazwischen befindet sich eine graue Fläche. Wir sollten vielleicht versuchen, einige Community-Standards für Meta zu vereinbaren.
Peter Taylor

@PeterTaylor, ich denke wir haben eine Art Patt erreicht. Mein pscheint jetzt ganz optimal zu sein, und deines mainwar besser (ich bin nicht sicher, ob es optimal ist, aber ich kann es nicht weiter verbessern). Abgesehen von einer neuen genialen Programmstruktur war der einzige Weg, den Code des anderen zu kopieren.
Ugoren

BTW Wie zählst du deine Charaktere? Weil ich deine neueste Version 138 Zeichen mache, nicht 136.
Peter Taylor

2

J, 44 39 38 37 Bytes

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

Verwendet die Iteration, um den nächsten Satz zu erstellen, der anfänglich mit 1 (repräsentiert _) beginnt .

Verwendung

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

Erläuterung

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

Nett! Ich persönlich habe es nicht versucht, aber ich liebe es, die Agenda zu verwenden - @.vielleicht könnte es in Kombination mit $:hier von Nutzen sein? ZB sowas (zero case)`(positive case)`(negative case)@.*oder vielleicht sogar ":@_:`(positive case)`(|."1@$:)@.*.
Conor O'Brien

Ich habe keine rekursive Lösung versucht, aber ich könnte es versuchen.
Meilen

2

R , 141 139 137 Bytes

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

Probieren Sie es online!

-15 Bytes danke auch Giuseppes Verwendung '('als Identitätsfunktion; writeanstatt catdie Ausgabe zu drucken; kluger Gebrauch von %x%.

-2 Bytes dank Kirill L. mit cstatt '('als Identitätsfunktion.


könnte hier ein Kronecker-Produkt funktionieren? %x%? Es könnte einige Probleme geben, wenn man abwechselnde Reihen nimmt ...
Giuseppe

@ Giuseppe Ich habe versucht, aufbauend auf Ihrer Antwort "Erstellen Sie ein" H "aus kleineren" H "" ... Ich werde es noch einmal versuchen.
JayCe

Ah, das hast du also befürwortet. Das ist der einzige Grund, an den ich auch gedacht kronhabe! Ich würde mir vorstellen, dass dies 125 Bytes erreichen sollte, wenn wir den richtigen Ansatz finden.
Giuseppe

Sie können `(`als Identitätsfunktion verwenden, sodass Sie writedirekt anstelle von catund eine forSchleife verwenden können. 141 Bytes
Giuseppe

@ Giuseppe Ich hatte keine Ahnung, (wie man das so macht, oder dass if man damit aus zwei Funktionen auswählen kann. Und ich werde anfangen zu schreiben ... spart eine Menge "\ n".
JayCe

1

Python, 177 164 Zeichen

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

Da Sie Python 2 verwenden, müssen Sie die Ergebnisse von inputas nicht konvertieren int. Ihre letzten beiden Zeilen könnten verkürzt werden aufprint"\n".join(r[::N>0 or-1])
Steven Rumbalski

@Steven Ich habe Änderungen vorgenommen. Vielen Dank.
Ante

1

Perl, 113 Zeichen

$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

Erweitert:

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

Innere rekursive Funktion, dann kümmern Sie sich bei Bedarf um die Rückwärtsausgabe

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`

Weniger golfen

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

Prüfung

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

Batch, 265 262 242 236 235 Bytes

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

Bearbeiten: 12 bis 19 Bytes dank @ l4m2 gespeichert. 8 Bytes durch Entfernen der unnötigen %a%Variablen gespart .


Dies für 247 Bytes.
Conor O'Brien

@ ConorO'Brien Wohlgemerkt wäre es 261, wenn ich alle CRs sowie die LFs zählen würde (was Sie sicher nicht tun müssen, aber ich bin so faul).
Neil

Sie entfernen also keine CRs aus Ihrem Code? Auch wenn es von .BAT-Dateien nicht benötigt und von SE trotzdem entfernt wird? : P
Conor O'Brien

@ ConorO'Brien Es ist eine Strafe, die ich akzeptiere, wenn ich Notepad zum Schreiben von Batch-Dateien benutze.
Neil

Kannst du so etwas machen 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?
14.



0

Prolog (SWI) , 265 232 213 Bytes

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.

Probieren Sie es online!


0

PowerShell , 111 Byte

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

Probieren Sie es online!

Weniger golfen:

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{
        '_'
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.