Noten ASCII-Art Generator

31

Hinweis : Anders Kaseorg warnt mich, dass dies ein Duplikat einer anderen vorherigen Frage sein könnte . Es scheint so, und es tut mir leid, dass ich diese Frage nicht gefunden habe, bevor ich diese gepostet habe. Dennoch hat diese Frage nur eine Antwort erhalten, und diese ist einfacher, nur für den Fall, dass Sie diesmal alle versuchen möchten. Ich werde es verstehen, wenn diese Frage als Duplikat markiert wird.

Die Herausforderung

Bei einer Eingabe wie dieser:

8g 8Df 4cs 2C 1A

Schreiben Sie das kürzeste Programm / die kürzeste Funktion, die eine Ausgabe wie die folgende erzeugt:

    /\                                         -o-
   | |
---|-|---------------------------------------------------|-|
   |/                                                    | |
---/|--------|\----b-*-----------------------------------|-|
  / |        | |    |                  o                 | |
-|--|--------|------|-----------------|------------------|-|
 | (| \      |      | |               |                  | |
-|--|--)----*-------|/---------|------|------------------|-|
  \ | /                        |      |                  | |
-----|-------------------------|-------------------------|-|
     |                         |
   *_/                      #-*-

Regeln

Die Ausgabe muss aus einem fünfzeiligen Stab bestehen, der mit der Zeichnung eines G-Schlüssels genau wie oben beginnt, links vom Stab ausgerichtet ist und nach dem Start des Stabes eine einzelne Spalte verlässt.

    /\  
   | |
---|-|--
   |/   
---/|---
  / |   
-|--|---
 | (| \ 
-|--|--)
  \ | / 
-----|--
     |  
   *_/
^
Single column

Die Notizen müssen je nach Typ mit einem *oder einem oZeichen beginnen .

Es müssen genau acht Trennspalten für jedes *oder ein oZeichen vorhanden sein:

    /\                                         -o-
   | |
---|-|---------------------------------------------------|-|
   |/                                                    | |
---/|--------|\----b-*-----------------------------------|-|
  / |        | |    |                  o                 | |
-|--|--------|------|-----------------|------------------|-|
 | (| \      |      | |               |                  | |
-|--|--)----*-------|/---------|------|------------------|-|
  \ | /                        |      |                  | |
-----|-------------------------|-------------------------|-|
     |                         |
   *_/                      #-*-
   ↑        ↑        ↑        ↑        ↑        ↑        ↑
   8 columns of separation

Der Stab muss mit dem rechts ausgerichteten Abschlusszeichen enden, wie im Beispiel gezeigt. Der linke Balken des Abschlusszeichens muss 8 Spalten von der letzten Note entfernt sein.

Die Eingabe ist eine einzelne Zeichenfolge, die die Noten enthält (mindestens eine, keine leeren Eingaben), wobei jede durch ein Leerzeichen getrennt ist (Sie können davon ausgehen, dass jede Note eine richtige Note ist, sodass Sie nicht nach Fehlern suchen müssen). Sie können die Eingabe auch als ein Array von Zeichenfolgen mit einer Note pro Element im Array annehmen. Für jede Note ist das erste Zeichen der Nenner der Notenlänge ( 1für eine ganze Note / ein halbes Blatt beginnt er mit o; 2für eine halbe Note / ein Minimum beginnt er mit o; 4für eine Viertelnote / einen Schritt beginnt er mit *; und 8für eine Achtel note / quaver , beginnt mit*). Das zweite Zeichen ist die Notiz (siehe nächste Tabelle), und das dritte optionale Zeichen ist foder Ffür flache Noten und soder Sfür scharfe Noten.

    ---    A (ledger line)
           G
--------   F
           E
--------   D
           C
--------   b
           a
--------   g
           f
--------   e
           d
    ---    c (ledger line)

Natürlich muss die Eingabe die Groß- und Kleinschreibung der Noten berücksichtigen, aber Sie können die Groß- fund Kleinschreibung der und s-Modifikatoren auswählen .

Notiert cund Afügt zwei -(Hauptbuchzeilen) an jeder Seite hinzu, da die Belegschaft erweitert werden muss. Notizen dund Gsind aus dem Personal, brauchen aber keine Hauptbuchzeilen.

Abgeflachte oder geschärfte Noten müssen links von der Note eine boder #zwei Positionen hinzufügen .

Die Stiele (falls vorhanden) müssen mit 4 vertikalen Balken gezeichnet werden. Noten von bund über müssen den Stiel nach unten und links von der Note ziehen. Noten von aund unter müssen den Stiel nach oben und rechts von der Note ziehen. Quaver müssen die Flagge immer nach rechts und genau wie gezeigt anbringen und müssen nicht gebeamt werden, wenn mehrere von ihnen hintereinander sind.

--------------------------

-----|\----b-*------------
     | |    |             
-----|------|-------------
     |      | |           
----*-------|/---------|--
    ↑↑                 |  
----||------↑↑---------|--
    ||      ||         |
    ||      ||      #-*-
    |\      |\        ↑↑
    | Stem  | Note    | Stem
    Note    Stem      Note

Wie üblich kann Ihr Programm / Ihre Funktion die Ausgabe direkt zeichnen oder einen String, ein Array von Strings, eine Matrix von Zeichen oder ein anderes vernünftiges Format zurückgeben.

Nützliche Links

Das ist , also kann das kürzeste Programm / die kürzeste Funktion für jede Sprache gewinnen!

Bonus: Versuche Beispiele mit berühmten Melodien zu schreiben und lass jeden raten, um welche Melodie es sich handelt!

Charlie
quelle
Sandkasten .
Charlie
Duplikat?
Anders Kaseorg
... also können wir nicht einmal den Fall des Briefes verwenden, um zu sagen, wie der Stiel gezeichnet werden soll?
Neil
1
@Neil Entschuldigung, ich fürchte, Sie können nicht. Ich habe mir diese Regel nicht ausgedacht und folgendes überprüft : "Die Stiele zeigen normalerweise nach unten für Noten in der Mittellinie oder höher und nach oben für die darunter liegenden".
Charlie
1
Können wir eine Reihe von Zeichenfolgen als Eingabe verwenden, wobei jede Zeichenfolge eine einzelne Note ist?
Shaggy

Antworten:

13

SOGL V0.12 , 178 175 174 173 172 171 Bytes

l9*6«+@*@¶¹┐∑:@┌ŗ4Ο"γ;]∑«;‽ΗmzΖH+īN D‼,ΨU‛y‚_○¤└yΨšI‘7n2∆╬5;{" -o-”;l3=?Jζ2%Ƨ#bWGk+;}Jz7m««:U+;W7«κArBb3>?Ζo*ŗ}a2\?┌@ŗ}ē9*LI+a╬5b1>?4┐∙b8=?"■QD³‘┼}e9*5+a4-8a>?5+;2-;G↕№}╬5

Probieren Sie es hier aus! (θ zur Vereinfachung der Verwendung hinzugefügt; Um 171 Byte auszuführen, wird erwartet, dass sich die Eingabe auf dem Stapel befindet.)

Soweit ich das beurteilen kann, funktioniert es, aber wenn Sie Probleme haben, sagen Sie es mir.

Erläuterung:

Erster Teil: Canvas-Erstellung

l                                get the length of that array
 9*                              multiply by 9
   6«+                           add 12
      @*                         get that many spaces
        @¶                       push a space and a newline
          ¹                      put all the strings on the stack in an array
           ┐∑                    join with vertical bars
             :                   duplicate that string (which is a line with the ending barline but no staff)
              @┌ŗ                replace spaces with dashes (to make it a line with staff)
                 4Ο              encase 4 copies of the space lines in lines with the dashes
                   "...‘         push the G-clef without newlines
                        7n       split into an array of items of length 7
                          2∆╬5   at 1-indexed coordinates [2; -1] place the G-clef in the staff lines, extending the arrays size 
                              ;  get the input split on spaces back on top of the stack

Zweiter Teil: Loop, Noten Kopf Platzierung

{                        loop over the input split on spaces
" -o-”                    push a template for a note head and leger lines
      ;                   get the input optop
       l3=?            }  if the length of the input is 3, then
           J                pop the last letter off from the input
            ζ               get its unicode point
             2%             modulo 2
               Ƨ#bW         get its index in "#b"
                   G        get the template ontop
                    k       remove its 1st letter
                     +      join the replaced input and the template
                      ;     get the input back ontop to be consisntent with how the if started

sidequest: parse the rest of the inputs
J                  pop the last letter off of the remaining input string (the note), leaving the note length as string on the stack below
 z                 push the lowercase alphabet
  7m               get its first 7 letters
    ««             put the first 2 at the end
      :            duplicate it
       U+          append it uppercased to the original
         ;W        get the notes letter ontop and get its 1-indexed index in that just created string
           7«κ     subtract it from 14
              A    save on variable A
               r   convert the note length to a number
                B  save on variable B

b3>?    }          if b>3 (aka if note length is either 4 or 8)
    Ζo*ŗ             replace "o" with "*"
         a2\?   }  if a divides by 2 (aka there isn't staff nor leger lines required)
             ┌@ŗ     replace "-" with " "

ē          push the value of variable E and after that increase it (default is user input number, which errors and defaults to 0)
 9*        multiply by 9
   LI+     increase by 11
      a    push variable a
       ╬5  at those positions (e*9+11, a) insert the note head template in the canvas

dritter Teil: Flaggen und Stiele

b1>?                      if b (note length)>1 (aka if the stem is needed at all)
    4┐∙                   get an array of 4 vertical bars
       b8=?       }       if b==8 (aka if the flag is needed)
           "■QD³‘           push "\    |"
                 ┼          add verically-down-then-horizontally-right

e9*                       push e*9 (now e starts with 1 as it's been increased) (the X coordinate for the flag)
   5+                     add 5 to it
     a4-                  push a-4 (the Y coordinate, 4 less than the note head as arrays get inserted from the top-left corner)
        8a>?         }    if 8>a (aka if the flag needs to be rotated)
            5+              add 5 to the Y coordinate
              ;2-;          subtract 2 from the X coordinate
                  G         get the stem&flag or stem ontop
                   ↕№       reverse it vertically and mirror characters
                      ╬5  insert the array of the stem and maybe flag at those coordinates
dzaima
quelle
Ihr Code ist fast perfekt. Der einzige Trottel ist, dass die Note 2bsin Ihrem Beispiel den Stiel nach unten zeigen muss.
Charlie
@CarlosAlejo behoben
dzaima
Groß! Und danke für die Erklärung!
Charlie
10

JavaScript (ES6), 616.527 Byte

Vielen Dank an @shaggy für das Entfernen von fast 90 Bytes

Ich hatte keine Ahnung von Notizen ... bis jetzt hoffe ich habe es richtig verstanden.

f=i=>i.map((v,p)=>(k[e=(w=q+12)*(l="AGFEDCbagfedc".search(v[1]))+p*9+12]="o*"[(s=v[0])>3|0],l<1|l>11&&(k[e-1]=k[e+1]="-"),(t=v[2])&&(k[e-2]="b#"[t>"f"|0]),--s&&[1,2,3,4].map(i=>(k[(b=l<8)?e+w*i-1:e-w*i+1]="|",s>6&&( b?k[e+w*4]="/":k[e-w*4+2]="\\",k[b?e+w*3+1:e-w*3+3]='|')))),k=[...`    /\\  ${s=" ".repeat(q=i.length*9)}  
   | |  ${s}    
---|-|--${l="-".repeat(q)+"|-|"}
   |/   ${t=s+"| |"}
---/|---${l}
  / |   ${t}
-|--|---${l}
 | (| \\ ${t}
-|--|--)${l}
  \\ | / ${t}
-----|--${l}
     |  ${s}   
   *_/  ${s}`])&&k.join``

console.log(f(["8g","8Df","4cs","2C","1A"]))
.as-console-wrapper { max-height: 100% !important; top: 0 }
.as-console-row:after { display: none !important; }

Erläuterung

f=i=>i.map((v,p)=>( // for each note

  k[e=(w=q+12)*(l="AGFEDCbagfedc".search(v[1]))+p*9+12]= // position in 1D array to set the note to
  "o*"[(s=v[0])>3|0], // note value (either o or *)

  l<1|l>11&&(k[e-1]=k[e+1]="-"), // add leger line

  (t=v[2])&&(k[e-2]="b#"[t>"f"|0]), // add sharp or flat

  --s&&[1,2,3,4].map(i=> // add the 4 stem lines
                     (k[(b=l<8)?e+w*i-1:e-w*i+1]="|", // durration over eigth note => add stem

                      s>6&&( // if to add a flag
                        b?k[e+w*4]="/":k[e-w*4+2]="\\", // add flag either on left or the right side

                        k[b?e+w*3+1:e-w*3+3]='|') // add the line after the flag
                     )
                    )
),
// template, extended to the final length with lines
k=[...`    /\\  ${s=" ".repeat(q=i.length*9)}  
   | |  ${s}   
---|-|--${l="-".repeat(q)+"|-|"}
   |/   ${t=s+"| |"}
---/|---${l}
  / |   ${t}
-|--|---${l}
 | (| \\ ${t}
-|--|--)${l}
  \\ | / ${t}
-----|--${l}
     |  ${s}   
   *_/  ${s}`])&&k.join``
Bögen
quelle
Ich denke, Sie können einige Bytes sparen , indem Sie t[0]und speichern t[2], und dann einfach tunq=t.length*9
Stephen
2
Willkommen bei PPCG. Sehr schöne erste Antwort :) Es gibt aber noch ein bisschen mehr Möglichkeiten zum Golfen. Ich habe einen kurzen Blick darauf geworfen und es auf 520 Bytes reduziert , was Ihnen einen guten Start ermöglichen sollte.
Shaggy
Sicherlich würde ein Ersetzen von + atob / btoa einige Bytes sparen
Downgoat
1
@ Shaggy vielen Dank. Ich habe viel zu lernen.
Bögen
Gern geschehen :) Sie haben einen freien Platz, nach s>6&&(dem Sie ein Byte sparen können. Sie können auch ein anderes Byte mit speichern, indem Sie (w=q+12)mit w, repeat(q=i.length*9)mit repeat(w=i.length*9)und repeat(q)mit ersetzen repeat(w,w+=12).
Shaggy
9

Charcoal , 180 171 168 163 Bytes

F⁵⁺⸿⸿×-⁺²⁷×⁸№θ ↑⁹←↙↓⁹J⁴¦⁹↑⁶↗¹↑²↖¹↓↙¹↓³↙²↓³ \M²↑(| ↘¹↙)↙¹↓²↙¹↑←_*F⪪θ «A⌕AGFEDCbagfedc§ι¹λJχλA⁺⁹χχ¿⁼³Lι§b#⁼§ι²s→P׳¬﹪λ²→P§o*›ι4¿›ι2¿›λ⁶«↗↑⁴¿›ι8«↘↘¹↓¹»»«↙↓⁴¿›ι8«↗↗¹↑¹

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

F⁵⁺⸿⸿×-⁺²⁷×⁸№θ ↑⁹←↙↓⁹

Drucken Sie die Daube.

J⁴¦⁹↑⁶↗¹↑²↖¹↓↙¹↓³↙²↓³ \M²↑(| ↘¹↙)↙¹↓²↙¹↑←_*

Notenschlüssel drucken.

F⪪θ «

Durchlaufen Sie jede Note.

A⌕AGFEDCbagfedc§ι¹λ

Finden Sie die Y-Koordinate der Notiz.

JχλA⁺⁹χχ

Das ist wirklich hinterhältig: Es χhandelt sich um eine Variable, die auf 10 vordefiniert ist. Dies ist genau die X-Koordinate des Versehens der ersten Note, falls vorhanden. Nach dem Springen zu dieser Position wird 9 hinzugefügt, die die nächste Notenposition darstellt.

¿⁼³Lι§b#⁼§ι²s→

Drucken Sie den Unfall aus, falls vorhanden.

P׳¬﹪λ²→P§o*›ι4

Drucken Sie ggf. die Hauptbuchzeilen und die Notiz aus. Tatsächlich wird die Linie auf einer geraden y-Koordinate gedruckt, obwohl das Drucken über die Daube natürlich keine Auswirkung hat.

¿›ι2

Nichts mehr für Halbrebe zu tun.

¿›λ⁶«

Für Noten unterhalb des Mittelpunkts

↗↑⁴

ziehe den Stiel nach oben,

¿›ι8«↘↘¹↓¹

und die Flagge für Achtel.

»»«

Für Noten über dem Mittelpunkt

↙↓⁴

den Stiel nach unten ziehen,

¿›ι8«↗↗¹↑¹

und die Flagge für Achtel.

Neil
quelle
Du hast SOGL geschlagen! :-)
Charlie
@CarlosAlejo Ich habe damit gerechnet. Aber ich hatte erwartet, dass es mich auch um 20% schlagen würde.
Dzaima
@dzaima vielleicht, wenn es eine reine ASCII-Kunst-Herausforderung wäre, aber diese hat auch einen logischen Teil, der die Ausgabe von der Eingabe abhängig macht. Trotzdem gewöhne ich mich immer noch daran, was jede Sprache besser kann.
Charlie