Nuty ASCII-art generator

31

Uwaga : Anders Kaseorg ostrzega mnie, że może to być duplikat innego poprzedniego pytania . Wydaje się, że tak, i przepraszam, że nie znalazłem tego pytania przed opublikowaniem tego. Niemniej jednak na to pytanie otrzymano tylko jedną odpowiedź, a to jest prostsze, na wypadek, gdybyście wszyscy chcieli spróbować tym razem. Zrozumiem jednak, czy to pytanie zostanie ostatecznie oznaczone jako duplikat.

Wyzwanie

Biorąc pod uwagę takie dane wejściowe:

8g 8Df 4cs 2C 1A

Napisz najkrótszy program / funkcję, która generuje takie wyjście:

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

Zasady

Dane wyjściowe muszą składać się z pięcioliniowego pięciolinii rozpoczynającego się od narysowania klucza G dokładnie tak, jak pokazano powyżej, wyrównanego do lewej strony pięciolinii i pozostawiającego jedną kolumnę po rozpoczęciu pięciolinii.

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

Nuty muszą zaczynać się *od oznaku lub w zależności od ich rodzaju.

Nie musi być dokładnie osiem kolumn oddzielenia każdego *lub oznaku:

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

Personel musi kończyć się terminatorem wyrównanym do prawej, jak pokazano w przykładzie. Lewy pasek terminatora musi być oddzielony 8 kolumnami od ostatniej nuty.

Wejście będzie pojedynczym ciągiem zawierającym nuty (co najmniej jeden, bez pustych danych wejściowych), każdy oddzielony spacją (możesz uznać, że każda nuta będzie poprawna, więc nie musisz sprawdzać błędów). Możesz również wziąć dane wejściowe jako tablicę ciągów, z notatką na element w tablicy. Dla każdej nuty pierwszy znak będzie mianownikiem długości nuty ( 1dla całej nuty / półprzewodnika rozpoczyna się od o; 2dla półnuty / minimu rozpoczyna się od o; 4dla ćwierćnuty / ćwierćnuty zaczyna się od *; a 8dla ósmej notatka / ósemka , zaczyna się od*). Druga postać będzie notatka (patrz następna tabela), a trzeci, opcjonalny postać będzie falbo Fpłaskich i notatek slub Sostrych nut.

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

Oczywiście dane wejściowe muszą uwzględniać wielkość liter w notatkach, ale możesz wybrać wielkość liter fi smodyfikatory.

Notatki ci Anależy dodać dwie -(linie księgi), po jednej z każdej strony, ponieważ muszą one rozszerzyć pięciolinię. Notuje di nie Gma wśród personelu, ale nie potrzebuje linii księgi.

Spłaszczone lub zaostrzone nuty muszą dodać blub #dwie pozycje po lewej stronie nuty.

Pędy (jeśli występują) należy narysować 4 pionowymi prętami. Nuty z bgóry i powyżej muszą rysować trzon w dół i po lewej stronie nuty. Nuty z adołu i do dołu muszą rysować trzon w górę i po prawej stronie nuty. Osłony muszą dodawać flagę, zawsze w prawo i dokładnie tak, jak pokazano, i nie muszą być przesyłane, jeśli jest ich kilka z rzędu.

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

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

Jak zwykle, twój program / funkcja może bezpośrednio narysować wyjście lub zwrócić ciąg, tablicę ciągów, macierz znaków lub dowolny inny rozsądny format.

Przydatne linki

To jest , więc może wygrać najkrótszy program / funkcja dla każdego języka!

Premia: spróbuj pisać przykłady ze słynnymi melodiami i pozwól każdemu zgadnąć, która to melodia!

Charlie
źródło
Piaskownica .
Charlie,
Duplikować?
Anders Kaseorg,
... więc nie możemy nawet użyć litery z literą, aby określić, w jaki sposób narysować trzon?
Neil,
1
@Neil przepraszam, obawiam się, że nie możesz. Nie nadrobiłem tej reguły, sprawdziłem, że : „pnie zwykle wskazują nuty na środkowej linii lub wyżej, a te poniżej”.
Charlie,
1
Czy możemy wziąć tablicę ciągów znaków, przy czym każdy ciąg znaków stanowi pojedynczą nutę jako dane wejściowe?
Kudłaty

Odpowiedzi:

13

SOGL V0.12 , 178 175 174 173 172 171 bajtów

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

Wypróbuj tutaj! (θ dodane dla ułatwienia użytkowania; aby działać jako 171 bajtów, oczekuje, że dane wejściowe znajdą się na stosie)

O ile mogę powiedzieć, to działa, ale jeśli znajdziesz jakieś problemy, powiedz mi.

Wyjaśnienie:

pierwsza część: tworzenie płótna

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

druga część: pętla, zwróć uwagę na położenie głowy

{                        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

trzecia część: flagi i łodygi

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
źródło
Twój kod jest prawie idealny. Jedyną nitpick jest to, że nuta 2bsw twoim przykładzie musi mieć trzon skierowany w dół.
Charlie,
@CarlosAlejo naprawiono
dzaima
Świetny! I dzięki za wyjaśnienie!
Charlie
10

JavaScript (ES6), 616 527 bajtów

Dzięki @shaggy za usunięcie prawie 90 bajtów

Nie miałem pojęcia o notatkach ... do tej pory mam nadzieję, że dobrze to zrozumiałem.

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

wyjaśnienie

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``
łuki
źródło
I pomyśleć można zaoszczędzić kilka bajtów, zapisując t[0]i t[2], a następnie po prostu zrobićq=t.length*9
Stephen
2
Witamy w PPCG. Bardzo ładna pierwsza odpowiedź :) Można jednak grać w golfa. Szybko przerzuciłem if i sprowadziłem go do 520 bajtów , co powinno dać dobry początek.
Kudłaty
Na pewno część zamiany + atob / btoa zaoszczędziłaby trochę bajtów
Downgoat
1
@Shaggy dziękuję bardzo. Muszę się jeszcze wiele nauczyć.
łuki
Nie ma za co :) Masz zbłąkane miejsce, po s>6&&(którym możesz zaoszczędzić bajt. Można również zapisać kolejny bajt z zastępując (w=q+12)ze w, repeat(q=i.length*9)ze repeat(w=i.length*9)i repeat(q)z repeat(w,w+=12).
Kudłaty
9

Węgiel drzewny , 180 171 168 163 bajtów

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

Wypróbuj online!Link jest do pełnej wersji kodu. Wyjaśnienie:

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

Wydrukuj pięciolinię.

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

Wydrukuj klucz.

F⪪θ «

Zapętlaj każdą notatkę.

A⌕AGFEDCbagfedc§ι¹λ

Znajdź współrzędną Y notatki.

JχλA⁺⁹χχ

To jest naprawdę podstępne: χ jest zmienną, która jest predefiniowana na 10, która jest dokładnie współrzędną X przypadkowej pierwszej nuty, jeśli ją posiada. Po przejściu do tej pozycji dodaje się do niej 9, co oznacza następną pozycję nuty.

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

Wydrukuj przypadkowy, jeśli taki istnieje.

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

W razie potrzeby wydrukuj linie księgi i notatkę. W rzeczywistości linia jest drukowana na dowolnej parzystej współrzędnej y, chociaż wydrukowanie jej na pięciolinii nie ma oczywiście żadnego efektu.

¿›ι2

Nic więcej do roboty dla półbogów.

¿›λ⁶«

W przypadku notatek poniżej punktu środkowego

↗↑⁴

pociągnij trzon do góry,

¿›ι8«↘↘¹↓¹

i flaga dla ósemek.

»»«

W przypadku nut powyżej punktu środkowego

↙↓⁴

pociągnij łodygę w dół,

¿›ι8«↗↗¹↑¹

i flaga dla ósemek.

Neil
źródło
Pokonałeś SOGL! :-)
Charlie,
@CarlosAlejo Spodziewałem się, że tak się stanie. Ale spodziewałem się, że pobije mnie to także o 20%.
dzaima
@dzaima może byłby wyzwaniem czysto ASCII, ale ten ma również część logiczną, która sprawia, że ​​wyjście zależy od danych wejściowych. Niemniej jednak wciąż przyzwyczajam się do tego, co każdy język może zrobić lepiej.
Charlie,