Générateur de partitions ASCII

31

Remarque : Anders Kaseorg m'avertit que cela pourrait être un doublon d' une autre question précédente . Il semble que oui, et je suis désolé de ne pas avoir trouvé cette question avant de poster celle-ci. Néanmoins, cette question n'a reçu qu'une seule réponse et celle-ci est plus simple, juste au cas où vous voudriez tous essayer cette fois. Je comprendrai si cette question finit par être marquée comme doublon.

Le défi

Étant donné une entrée comme celle-ci:

8g 8Df 4cs 2C 1A

Écrivez le programme / la fonction la plus courte qui produit une sortie comme celle-ci:

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

Règles

La sortie doit consister en une portée à cinq lignes commençant par le dessin d'une clé en G exactement comme indiqué ci-dessus, alignée à gauche de la portée et en laissant une seule colonne après le début de la portée.

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

Les notes doivent commencer par un *ou un ocaractère selon son type.

Il doit y avoir exactement huit colonnes de séparation pour chaque *ou un ocaractère:

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

Le bâton doit se terminer avec la terminaison alignée à droite, comme indiqué dans l'exemple. La barre de gauche du terminateur doit être séparée de 8 colonnes de la dernière note.

L'entrée sera une chaîne unique contenant les notes (au moins une, aucune entrée vide), chacune séparée par un espace (vous pouvez considérer que chaque note sera la bonne, donc pas besoin de vérifier les erreurs). Vous pouvez également prendre l'entrée comme un tableau de chaînes, avec une note par élément dans le tableau. Pour chaque note, le premier caractère sera le dénominateur de la longueur de la note ( 1pour une note entière / demi-fibre , commence par o; 2pour une demi-note / minim , commence par o; 4pour une noire / crotchet , commence par *; et 8pour une huitième note / tremblement , commence par*). Le deuxième caractère sera la note (voir le tableau suivant) et le troisième caractère facultatif sera fou Fpour les notes plates et sou Spour les notes aiguës.

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

Évidemment, l'entrée doit respecter la casse des notes, mais vous pouvez choisir la casse des modificateurs fet s.

Notes cet Adoivent ajouter deux -(lignes de grand livre), un de chaque côté, car ils doivent prolonger la portée. Notes det Gsont hors du personnel mais n'ont pas besoin de lignes de grand livre.

Les notes aplaties ou aiguisées doivent ajouter bou #deux positions à gauche de la note.

Les tiges (le cas échéant) doivent être dessinées avec 4 barres verticales. Les notes de bdessus et de dessus doivent tirer la tige vers le bas et sur le côté gauche de la note. Les notes de aet en dessous doivent tirer la tige vers le haut et sur le côté droit de la note. Les quavers doivent ajouter le drapeau, toujours à droite et exactement comme indiqué, et n'ont pas besoin d'être rayonnés s'il y en a plusieurs dans une rangée.

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

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

Comme d'habitude, votre programme / fonction peut directement dessiner la sortie ou renvoyer une chaîne, un tableau de chaînes, une matrice de caractères ou tout autre format raisonnable.

Liens utiles

C'est , donc le programme / la fonction la plus courte pour chaque langue peut gagner!

Bonus: essayez d'écrire des exemples avec des mélodies célèbres et laissez tout le monde essayer de deviner de quelle mélodie il s'agit!

Charlie
la source
Bac à sable .
Charlie
Dupliquer?
Anders Kaseorg
... donc nous ne pouvons même pas utiliser le cas de la lettre pour dire dans quelle direction dessiner la tige?
Neil
1
@Neil désolé, je crains que vous ne puissiez pas. Je n'ai pas inventé cette règle, j'ai vérifié que : "les tiges pointent généralement vers le bas pour les notes sur la ligne médiane ou supérieure, et vers le haut pour celles ci-dessous".
Charlie
1
Pouvons-nous prendre un tableau de chaînes, chaque chaîne étant une seule note, en entrée?
Shaggy

Réponses:

13

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

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

Essayez-le ici! (θ ajouté pour la facilité d'utilisation; pour fonctionner comme 171 octets, il s'attend à ce que l'entrée soit sur la pile)

Autant que je sache, cela fonctionne, mais si vous rencontrez des problèmes, dites-le-moi.

Explication:

première partie: création de toile

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

deuxième partie: boucle, placement de la tête de note

{                        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

troisième partie: drapeaux et tiges

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
la source
Votre code est presque parfait. Le seul problème est que la note 2bsde votre exemple doit avoir la tige pointée vers le bas.
Charlie
@CarlosAlejo fixed
dzaima
Génial! Et merci pour l'explication!
Charlie
10

JavaScript (ES6), 616 527 octets

Merci @shaggy d' avoir supprimé près de 90 octets

Je n'avais aucune idée des notes ... jusqu'à présent, j'espère avoir bien compris.

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

explication

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``
arcs
la source
Je pense que vous pouvez enregistrer quelques octets en enregistrant t[0]et t[2], puis faitesq=t.length*9
Stephen
2
Bienvenue chez PPCG. Très belle première réponse :) Il y a cependant un peu plus de golf qui peut être fait. J'ai pris un rapide passage sur if et je suis descendu à 520 octets , ce qui devrait vous donner un bon départ.
Shaggy
Certainement, remplacer + atob / btoa permettrait d'économiser quelques octets
Downgoat
1
@Shaggy merci beaucoup. J'ai beaucoup à apprendre.
arcs
Vous êtes les bienvenus :) Vous disposez d'un espace parasite après s>6&&(quoi vous pouvez économiser un octet. Vous pouvez également enregistrer un autre octet avec en remplaçant (w=q+12)par w, repeat(q=i.length*9)avec repeat(w=i.length*9)et repeat(q)avec repeat(w,w+=12).
Shaggy
9

Charbon de bois , 180 171 168 168 163 octets

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

Essayez-le en ligne! Le lien est vers la version verbeuse du code. Explication:

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

Imprimez la portée.

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

Imprimez la clé.

F⪪θ «

Parcourez chaque note.

A⌕AGFEDCbagfedc§ι¹λ

Trouvez la coordonnée Y de la note.

JχλA⁺⁹χχ

C'est vraiment sournois: χc'est une variable qui est prédéfinie à 10, qui est exactement la coordonnée X de la première note accidentelle, si elle en a une. Après avoir sauté à cette position, 9 y est ajouté, représentant la position de note suivante.

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

Imprimez l'accidentel, s'il y en a un.

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

Imprimez les lignes du grand livre si nécessaire et la note. En fait, la ligne est imprimée sur n'importe quelle coordonnée y même si l'impression sur la portée n'a bien sûr aucun effet.

¿›ι2

Rien de plus à faire pour les semi-fibres.

¿›λ⁶«

Pour les notes en dessous du point médian,

↗↑⁴

tirer la tige vers le haut,

¿›ι8«↘↘¹↓¹

et le drapeau des croches.

»»«

Pour les notes au-dessus du point médian,

↙↓⁴

tirer la tige vers le bas,

¿›ι8«↗↗¹↑¹

et le drapeau des croches.

Neil
la source
Vous battez SOGL! :-)
Charlie
@CarlosAlejo Je m'attendais à ce que cela se produise. Mais je m'attendais à ce qu'il me bate également de 20%.
dzaima
@dzaima peut-être s'il s'agissait d'un pur défi ASCII, mais celui-ci a également une partie logique qui fait que la sortie dépend de l'entrée. Néanmoins, je m'habitue toujours à ce que chaque langue peut faire de mieux.
Charlie