Erzeugen Sie eine ASCII-Padovan-Spirale

22

Dies ist die ASCII-Version dieser Herausforderung . Der ursprüngliche Beitrag wurde auf Wunsch von Martin Ender getrennt

Einführung

Ähnlich wie die Fibonacci-Sequenz ist die Padovan-Sequenz ( OEIS A000931 ) eine Folge von Zahlen, die durch Hinzufügen vorheriger Terme in der Folge erzeugt wird. Die Anfangswerte sind definiert als:

P(0) = P(1) = P(2) = 1

Das 0., 1. und 2. Glied sind alle 1. Die Wiederholungsbeziehung ist unten angegeben:

P(n) = P(n - 2) + P(n - 3)

Somit ergibt sich folgende Reihenfolge:

1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37, 49, 65, 86, 114, 151, 200, 265, 351, ...

Wenn Sie diese Zahlen als Seitenlänge von gleichseitigen Dreiecken verwenden, erhalten Sie eine schöne Spirale, wenn Sie sie alle zusammen platzieren, ähnlich wie bei der Fibonacci-Spirale:

Bildbeschreibung hier eingeben

Bild mit freundlicher Genehmigung von Wikipedia


Aufgabe

Ihre Aufgabe ist es, ein Programm zu schreiben, das diese Spirale durch ASCII-Kunst nachbildet und dessen Eingabe dem jeweiligen Begriff entspricht. Da ein Dreieck mit der Seitenlänge 1 (1 Zeichen) in ASCII nicht gut darstellbar ist, wurden die Seitenlängen um den Faktor 2 erweitert. Das Dreieck mit der Seitenlänge 1 wird also tatsächlich folgendermaßen dargestellt:

 /\
/__\

Wenn also zum Beispiel die Eingabe 5 war (das 5. Glied), sollte die Ausgabe sein:

   /\
  /  \
 /    \
/______\
\      /\
 \    /__\ 
  \  /\  /
   \/__\/

Die ersten 5 Terme waren 1, 1, 1, 2, 2, so dass das Dreieck aufgrund der Dilatation Seitenlängen von 2, 2, 2, 4, 4 aufwies. Ein weiteres Beispiel für Eingabe 8:

     __________
   /\          /\
  /  \        /  \
 /    \      /    \
/______\    /      \
\      /\  /        \
 \    /__\/          \
  \  /\  /            \
   \/__\/______________\
    \                  /
     \                /
      \              /
       \            /
        \          /
         \        /
          \      /
           \    /
            \  /
             \/

Regeln

  • Sie müssen das Ergebnis drucken und die Eingabe muss eine Ganzzahl sein, die der Termnummer entspricht
  • Nachgestellte und führende Zeilen sind zulässig, nachstehende Leerzeichen nach Zeilen sind ebenfalls zulässig
  • Ihr Beitrag muss mindestens bis zur 10. Amtszeit bearbeitet werden können (9)
  • Ihre Einreichung muss ein vollständiges Programm oder eine vollständige Funktion sein, die Eingaben entgegennimmt und das Ergebnis druckt
  • Rotationen der Ausgabe sind in 60-Grad-Vielfachen zulässig, aber die Größe der Dreiecke muss zusammen mit der Darstellung gleich bleiben
  • Es ist auch erlaubt, gegen den Uhrzeigersinn zu fahren
  • Standardlücken sind verboten

Sie können davon ausgehen, dass die Eingabe> 0 ist und das richtige Eingabeformat angegeben wird.

Wertung

Das ist , also gewinnt der kürzeste Code in Bytes. Ein frohes neues Jahr euch allen!

Andrew Li
quelle
1
Meine Sprache Turtlèd kann Eingaben zur Basis 10 verarbeiten, aber diese Herausforderung wäre um einiges einfacher, wenn sie als unärgernd angesehen würden. wäre das erlaubt
Destructible Lemon
1
@ Zerstörbare Wassermelone Ja. Die Eingabe muss in irgendeiner Form eine Ganzzahl sein.
Andrew Li
cool. Ich werde jetzt anfangen daran zu arbeiten
Destructible Lemon
3
Warten Sie eigentlich ist es immer noch sehr schwer
Destructible Lemon

Antworten:

13

Befunge, 871 836 798 Bytes

&00p45*:10p20p030p240p050p060p9010gp9110gp1910gp1-91+10gpv
<v-g03+g06*2g041g055_v#!:%6:p06p05+p04g05g06:g04<p*54+292<
->10g:1\g3+:70p110gv >:5- #v_550g:01-\2*40g+1-30g
/\110:\-g03:\1:g055 _v#!-4:<vp01:-1g01-g03-1\-
^1<v07+1:g07< p08p < >:1-#v_550g:01-\40g+60g+1-30g-50g>v
 _0>p80gp:5-|v1\+66\:p\0\9:$<:p02:+1g02-g03+g06-\g04\1:<
0v|-g00:+1$$<>\p907^>p:!7v>3-#v_550g:30g+:30p1\0\-
1>10g+::0\g3-:70p\0^^07<v<>50#<g::30g+:30p-1-01-\
v >\$0gg> :1+10gg1- #v_^>0g10gg*+\:!2*-70g2+10gv>:#->#,"_"$#1_:1#<p
+1+g03$_^#`gg011+3:+3<g07\+*2+*`0:-\gg01+5g07:g<>1#,-#*:#8>#4_$#:^#
>55+,p30g40p10gg10g1>#v_
#v:#p0$#8_:$#<g!#@_0^ >
 >>:180gg`>>#|_:2+80gg:!v
3+^g\0p08:<vgg08+2::+3<$_100p1-v>g,\80gg+\80gp:2+90g:!01p\80gp
!#^_80g:1+^>\180gg`+!#^_20g80g`
5*g10!g09p04-1-\0\+g04:gg08:p09<^3`0:gg08+1:::$$_1#!-#\\:,#\<g

Probieren Sie es online!

Wie so oft bei Befunge gibt es einen Algorithmus, mit dem wir das Muster von oben nach unten rendern können, da es aufgrund des begrenzten verfügbaren Speicherplatzes einfach nicht möglich ist, es zuerst in den Speicher zu rendern.

Das funktioniert, indem Sie zunächst eine einfache Datenstruktur aufbauen, die die Kanten darstellt, die zum Zeichnen der Spirale erforderlich sind. In der zweiten Stufe wird diese Struktur dann von oben nach unten analysiert, wobei die für jede Ausgabezeile erforderlichen Kantenfragmente gerendert werden.

Mit dieser Technik können wir bis zu n = 15 in der Referenzimplementierung unterstützen, bevor ein Überlaufproblem in den 8-Bit-Speicherzellen auftritt. Interpreter mit einer größeren Zellengröße sollten in der Lage sein, bis zu n = 25 zu unterstützen, bevor der Speicher voll wird.

James Holderness
quelle
das ist sehr beeindruckend ... aber finden Sie, dass Sie diese Programme lesen können? lol für mich sieht es so zufällig aus. Wie baut es die Datenstruktur auf? Welche Datenstruktur wird verwendet? Vielen Dank!
Don Bright
1

go, 768 bytes

func 卷(n int){
    数:=0
    p:=[]int{1,1,1}
    for i:=3;i<n;i++ {p=append(p,p[i-2]+p[i-3])}
    宽:=p[len(p)-1]*10+10
    素:=make([]int,宽*宽)
    for 数=range 素 {素[数]=32}
    for i:=0;i<数;i+=宽 {素[i]=10}
    态:=[]int{1,1,宽/2,宽/2,92}
    表:=[70]int{}
    s:="SRSQTSPQQ!QOQP~QQQQQQSQR~ORQR!OPOPTSQRQ$QPPQNQPPPXQQQQQQRRQXQRRRNOQPQ$"
    for i:=range s {表[i]=int(s[i])-33-48}
    表[49],表[59]=48,48
    for i:=0;i<4*n;i++ {
        梴:=p[i/4]*2
        if 态[1]==0 {梴=梴*2-2}
        for k:=0;k<梴;k++ {
            址:=(态[2]+态[3]*宽)%len(素)
            if 素[址]==32 {素[址]=态[4]}
            态[2]+=态[0]
            态[3]+=态[1]
        }
        数=((态[0]+1)*2+态[1]+1)*5
        if i%4>2 {数+=35}
        for k:=0;k<5;k++ {态[k]+=表[数+k]}
    }
    for i:=0;i<宽*宽;i++ {fmt.Printf("%c",rune(素[i]))}
}

Das ist natürlich nicht optimal, aber es ist kein schlechter Start. Ich weiß, dass es für den Golfstandard wahrscheinlich ein bisschen einfach ist, aber es hat Spaß gemacht und ich hoffe, es macht nichts aus, wenn ich ein paar Notizen für das zukünftige Selbst hinterlasse.

Wie es funktioniert

Grundsätzlich simuliere ich eine 'Zeichenschildkröte' wie in LOGO auf einem ASCII-Pixelraster, aber die Schildkröte kann nur diese drei Befehle ausführen:

rt   - right turn, turn 120 degrees right (1/3 of a Turn)
rth  - right turn half, turn  60 degrees right (1/6 of a Turn)
fd n - forward, go forward n steps, drawing a trail of _, /, or \

Nun gehe ich für jedes Dreieck so vor, wobei P 2x die n-te Padovan-Zahl ist:

fd P
rt
fd P
rt 
fd P
rt
fd P
rth

Das vierte 'fd' bedeutet, dass ich die erste Seite jedes Dreiecks zurückverfolge. Dies hilft, zu einem schönen Ausgangspunkt für das nächste Dreieck zurückzukehren. Die halbe Rechtskurve stellt sicher, dass sich das nächste Dreieck in der richtigen Ausrichtung befindet.


Um die Schildkröte zu golfen, speichere ich 5 Zustandsvariablen in Array 态: x-Position, y-Position, x-Geschwindigkeit, y-Geschwindigkeit und 'Zeichenrune'. Bei jedem Animationsbild ist x + = x Geschwindigkeit, y + = y Geschwindigkeit und die Rune ist gezeichnet.

Dann habe ich den Tisch 表 aufgestellt, an dem steht, wie die Wende tatsächlich ausgeführt wird. Der Turncode ist aufgrund der Funktionsweise von ASCII-Grafiken schwierig. Es ist keine einfache Bewegung wie bei einer Pixelanzeige. Die Richtung der Schildkröte, die durch die x- und y-Geschwindigkeit bestimmt wird, bestimmt die Änderungen, die erforderlich sind, damit die Kurve richtig aussieht.

Zum Wenden werden die aktuellen x- und y-Geschwindigkeiten angezeigt und zu einem Index kombiniert.

xv = x velocity, yv = y velocity. 
i.e. a turtle facing down and to the right has 
xv of 1, and yv of 1. It can only face 6 
different directions. Formula is (xv+1)*2+yv+1

xv  yv    index
-1  -1    0
-1   0    1
-1   1    2
 1  -1    4
 1   0    5
 1   1    6

Dieser Index wird zum Nachschlagen eines Satzes von 5 Werten in Tabelle look verwendet. Diese 5 Werte in Tabelle 表 werden dann zu jeder der 5 Variablen in Zustand 态 addiert. Die Schildkröte wird dann effektiv gedreht und ist bereit für das nächste 'fd'.

Für die rechte halbe Kurve gibt es einen separaten Abschnitt der 表-Tabelle. Es wird um 7 * 5 oder 35 Einträge aus der ersten Tabelle in 表 versetzt.

Zuletzt habe ich einige einfache Codierungen der Ganzzahlen der Tabelle in eine ASCII-Zeichenfolge vorgenommen.

Ich weiß, ich könnte 'Bytes sparen', indem ich das Hanzi entferne, aber wie gesagt, das ist nicht optimal und es ist mehr Golf möglich ... Ich werde sie entfernen, wenn es keine andere mögliche Optimierung gibt. Diese Hanzi haben tatsächlich eine lose Bedeutung, die auf ihrer tatsächlichen Bedeutung basiert, und obwohl ich kein Chinesisch kann, hilft es mir, über das Programm nachzudenken.

数  index number
宽  screen width
素  pixel data
梴  length of side of triangle
态  current state
址  address of pixel
表  state transition table

Zum Testen des Codes benötigen Sie eine vollständige Golang-Datei mit diesem Header

package main
import "fmt"

und diese Fußzeile

func main ()  {
    for i := 0; i<15; i++ {
       卷(i)
    }
}

Vielen Dank

Don Bright
quelle