Sinusförmiger animierter ASCII-Kunsttext

11

Ich vermisse diese alten Demos, die die Fähigkeiten von Computern zeigen, als sie x86 statt i3, i5 und i7 hießen. Eine der ersten, die ich in meinem 386 gesehen habe, war die Unreal-Demo von Future Crew , die jetzt ihr 25-jähriges Bestehen feiert. In Minute 0:43 beginnt der erste Teil der Demo und wir sehen einen scrollenden Text, der einem sinusförmigen Pfad folgt. Versuchen wir, diesen Effekt in der ASCII-Kunst nachzuahmen!

Die Herausforderung

Angesichts dieses Weges:

***                                ***
   ***                          ***
      **                      **
        *                    *
         *                  *
         *                  *
          *                *
           **            **
             ***      ***
                ******

und einen Eingabetext, zeichnen Sie den Text, der diesem Pfad folgt, wie folgt:

Thi                                Golf! 
   s i                          de       Yay
      s                       Co            !
        P                     
         r                  d
         o                  n
          g                a
           ra            s 
             mmi      zle
                ng Puz

Beachten Sie, dass die Leerzeichen als Zeichen im Pfad gelten und dass sich der Pfad wiederholt, wenn der Text länger als das Beispiel ist.

Der Animationsteil

Nachdem Sie den Text gezeichnet haben, warten Sie 100 ms (um eine Animation mit ca. 10 fps zu erstellen) und zeichnen Sie den Text erneut, jedoch beginnend an der nächsten Position des Pfads. #nBerechnen n modulo 40und zeichnen Sie für den Rahmen an der folgenden Position des Pfads, wobei der Text immer links von der Leinwand ausgerichtet ist:

***                                ***
|  ***                          ***  |
|     **                      **     |
|       *                    *       |
|        *                  *        |
|        *                  *        |
|         *                *         |
|          **            **          |
|            ***      ***            |
|               ******               |
Position 0                 Position 39

Für Frame 10 haben wir also:

                           and Co
                        es       de 
                      zl            Go
                     z                l
                    u                  f
T                   P                  !
 h                                       
  is             ng                       Ya
     is       mmi                           y!
        Progra

Anmerkungen

  • Die Eingabe ist eine einzelne string(oder ein charbeliebiges Array) mit dem zu animierenden Text und hat immer mindestens 1 Zeichen.
  • Gültige zu animierende Zeichen sind die im druckbaren ASCII-Satz .
  • Der zu verfolgende Weg ist genau wie angegeben.
  • Der Text wird immer links von der Leinwand ausgerichtet, sodass der Text wie eine Flagge ohne Textverschiebung weht. Und mit Leinwand meine ich Bildschirm oder was auch immer Sie verwenden, um den Text anzuzeigen . ;-);
  • Frames müssen frei von Zeichen / Pixeln aus vorherigen Frames sein, es sei denn, das Zeichen / Pixel ist in beiden Frames gleich.
  • Die Geschwindigkeit der Animation spielt keine Rolle, solange sie reibungslos oder so schnell wie Ihr Gerät läuft (wir können mindestens 5 fps einstellen, dies ist jedoch keine Voraussetzung). Passen Sie einfach die Geschwindigkeit an, um es flüssig zu machen, und machen Sie sich keine Sorgen, wenn die Wartezeiten nicht genau gleich sind.
  • Die Animation wird endlos wiederholt.

Dies ist , also kann das kürzeste Programm oder die kürzeste Funktion, die den Text animieren kann, gewinnen!

Charlie
quelle
Verwandte . Sandkasten .
Charlie
1
Ich kann 38 Spalten anstatt 40 zählen.
Arnauld
1
@Arnauld Das liegt daran, dass es auf die Positionen im Pfad ankommt, nicht auf die Spalten.
Charlie
Oh ich verstehe. Macht Sinn.
Arnauld
Ist das als Ausgabe in Ordnung? Es zeigt den Eingang in Form einer Sinuswelle an und schleift endlos. Da das Video im Graphics Interchange-Format vorliegt, ist es natürlich schneller.
R. Kap

Antworten:

9

HTML + ES6, 241 244 237 Bytes

Nervenzusammenbruch:

  • HTML: 16 Bytes
  • JS-Funktion: 221 Bytes

let f =

s=>setInterval(_=>o.innerHTML=[...s].map((c,i)=>([j,y]=[...Array(40)].map((_,k)=>[j=k%20,y,y+=77732>>j&1?k<20||-1:0],y=0)[(i+p)%40],a[y]=a[y]||[...s].fill` `)[x]=(x+=j!=9,c),x=0,a=[],p++)&&a.map(r=>r.join``).join`
`,p=30)

f("This is Programming Puzzles and Code Golf! Yay!")
<pre id=o></pre>

Wie?

Den Weg bauen

Der folgende Code erstellt den Pfad:

[...Array(40)].map((_, k) =>
  [
    j = k % 20,
    y,
    y += 77732 >> j & 1 ? k < 20 || -1 : 0
  ],
  y = 0
)

Dies ergibt ein Array von Arrays, [j, y, z]wobei j die Position modulo 20 ist, y die y-Koordinate an dieser Position ist und z später nicht verwendet wird (es wird hier nur berechnet, um einige Bytes zu sparen).

Da der Pfad symmetrisch ist, müssen wir nur die 20 ersten Positionen codieren. Dazu verwenden wir eine Binärzahl, bei der jedes 1Bit bedeutet, dass y aktualisiert werden muss (+1 für die erste Hälfte, -1 für die zweite Hälfte).

001
   001
      01
        1
         1
         1
          1
           01
             001
                000

Wenn die erste Position auf das niedrigstwertige Bit abgebildet wird, ergibt dies:

00010010111110100100 as binary = 77732 as decimal

Da diese Binärzahl selbst auch symmetrisch ist, können wir sie für die 2. Hälfte in derselben Reihenfolge lesen.

Daher die Formel:

y += (77732 >> j) & 1 ? (k < 20 ? 1 : -1) : 0

was auch geschrieben werden kann als:

y += (77732 >> j) & 1 ? k < 20 || -1 : 0

Dabei ist k die Position und j die Position Modulo 20.

Das Aktualisieren von x ist viel einfacher: Wir müssen nur einen Sonderfall erkennen, indem wir die Position Modulo 20 mit 9 vergleichen.

Den Text zeichnen

Im folgenden Code wurde der oben beschriebene pathPfadbildungscode aus Gründen der Lesbarkeit durch eine Variable ersetzt.

s => setInterval(                       // set a periodic timer:
  _ =>                                  //   with an anonymous callback
    o.innerHTML =                       //   which updates the content of 'o'
      [...s].map((c, i) => (            //   for each character c of the string s
          [j, y] = path[(i + p) % 40],  //     retrieve j and y from the path
          a[y] = a[y] || [...s].fill` ` //     initialize a[y] if it's undefined
        )[x] = (x += j! = 9, c),        //     update a[y][x] / update x
        x = 0,                          //     initialize x
        a = [],                         //     initialize a[]
        p++                             //     increment the phase
      ) &&                              //   end of map()
      a.map(r => r.join``).join`\n`,    //   join everything together
  p = 30                                //   initial phase = interval period = 30
)                                       // end of timer definition
Arnauld
quelle
Das ist brillant und ziemlich nah an dem angeforderten Pfad, aber der Pfad ist nicht genau der, den ich gezeichnet habe. Die zwei Spalten, die zwei *vertikal enthalten, sind nicht ausgerichtet (auf derselben Höhe), und ein weiterer kleiner Nitpick. Aber ich muss sagen, ich weiß immer noch nicht, wie Ihr Code den Welleneffekt erzeugt (was macht das y+=155464?). Herzliche Glückwünsche!
Charlie
@CarlosAlejo Ich denke, der Pfad sollte jetzt festgelegt werden. Könnten Sie das bitte noch einmal überprüfen? Ich werde eine Erklärung der verwendeten Methode hinzufügen.
Arnauld
1
Pfad überprüft, und vielen Dank für die Erklärung!
Charlie