Lembaran musik ASCII-art generator

31

Catatan : Anders Kaseorg memperingatkan saya bahwa ini bisa menjadi duplikat dari pertanyaan sebelumnya . Sepertinya begitu, dan saya minta maaf saya tidak menemukan pertanyaan itu sebelum memposting yang ini. Meskipun demikian, pertanyaan itu hanya menerima satu jawaban dan yang ini lebih sederhana, kalau-kalau Anda semua ingin mencoba kali ini. Saya akan mengerti jika pertanyaan ini akhirnya ditandai sebagai duplikat.

Tantangan

Diberikan input seperti ini:

8g 8Df 4cs 2C 1A

Tulis program / fungsi terpendek yang menghasilkan keluaran seperti ini:

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

Aturan

Keluaran harus terdiri dari staf lima baris yang diawali dengan gambar G-clef persis seperti yang ditunjukkan di atas, disejajarkan ke kiri staf dan meninggalkan satu kolom setelah dimulainya staf.

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

Catatan harus dimulai dengan a *atau okarakter tergantung pada jenisnya.

Harus ada tepat delapan kolom pemisahan setiap *atau okarakter:

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

Staf harus diakhiri dengan terminator yang diluruskan ke kanan seperti yang ditunjukkan dalam contoh. Bilah kiri terminator harus dipisahkan 8 kolom dari not terakhir.

Input akan berupa string tunggal yang berisi catatan (setidaknya satu, tidak ada input kosong), masing-masing dipisahkan oleh spasi (Anda dapat menganggap setiap catatan akan menjadi yang tepat, jadi tidak perlu memeriksa kesalahan). Anda juga dapat mengambil input sebagai array string, dengan catatan per elemen dalam array. Untuk setiap not, karakter pertama akan menjadi penyebut panjang note ( 1untuk keseluruhan note / semibreve , dimulai dengan o; 2untuk half note / minim , dimulai dengan o; 4untuk quarter note / crotchet , dimulai dengan *; dan 8untuk yang kedelapan note / quaver , dimulai dengan*). Karakter kedua akan menjadi catatan (lihat tabel berikut), dan yang ketiga, karakter opsional akan menjadi fatau Funtuk nada datar dan satau Suntuk nada tajam.

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

Jelas, input harus menghormati kasing untuk catatan, tetapi Anda dapat memilih kasing fdan spengubah.

Catatan cdan Aharus menambahkan dua -(garis besar buku), satu di setiap sisi, karena mereka harus memperpanjang staf. Catatan ddan di Gluar staf tetapi tidak perlu garis besar.

Ratakan atau runcing catatan harus menambah batau #dua posisi di sebelah kiri catatan.

Batang (jika ada) harus digambar dengan 4 batang vertikal. Catatan dari bdan di atas harus menarik batang ke bawah dan di sisi kiri catatan. Catatan dari adan di bawah harus menarik batang ke atas dan di sisi kanan catatan. Quavers harus menambahkan bendera, selalu ke kanan dan persis seperti yang ditunjukkan, dan tidak perlu berseri-seri jika ada beberapa dari mereka secara berurutan.

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

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

Seperti biasa, program / fungsi Anda dapat langsung menggambar output atau mengembalikan string, array string, matriks karakter atau format lain yang masuk akal.

Tautan yang bermanfaat

Ini adalah , jadi semoga program / fungsi terpendek untuk setiap bahasa menang!

Bonus: cobalah menulis contoh dengan melodi terkenal dan biarkan semua orang mencoba menebak melodi yang mana itu!

Charlie
sumber
Kotak pasir .
Charlie
Duplikat?
Anders Kaseorg
... jadi kita bahkan tidak bisa menggunakan kasing surat untuk mengetahui cara menggambar batangnya?
Neil
1
@Neil maaf, saya khawatir Anda tidak bisa. Saya tidak membuat aturan itu, saya memeriksa bahwa : "batang biasanya menunjuk ke bawah untuk catatan di garis tengah atau lebih tinggi, dan naik untuk yang di bawah".
Charlie
1
Bisakah kita mengambil array string, dengan masing-masing string menjadi satu catatan, sebagai input?
Shaggy

Jawaban:

13

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

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

Coba Di Sini! (θ ditambahkan untuk kemudahan penggunaan; Untuk menjalankan sebagai 171 byte itu mengharapkan input berada di tumpukan)

Sejauh yang saya tahu ini berhasil, tetapi jika Anda menemukan masalah, katakan padaku.

Penjelasan:

bagian pertama: pembuatan kanvas

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

bagian kedua: lingkaran, perhatikan penempatan kepala

{                        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

bagian ketiga: bendera dan batang

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
sumber
Kode Anda hampir sempurna. Satu-satunya nitpick adalah catatan 2bsdalam contoh Anda harus memiliki batang mengarah ke bawah.
Charlie
@CarlosAlejo diperbaiki
dzaima
Besar! Dan terima kasih atas penjelasannya!
Charlie
10

JavaScript (ES6), 616 527 byte

Terima kasih @shaggy karena telah menghapus hampir 90 byte

Saya tidak tahu tentang catatan ... sampai sekarang, saya harap itu benar.

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

penjelasan

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``
busur
sumber
Saya pikir Anda dapat menyimpan beberapa byte dengan menyimpan t[0]dan t[2], dan kemudian lakukan sajaq=t.length*9
Stephen
2
Selamat datang di PPCG. Jawaban pertama yang sangat bagus :) Ada sedikit lebih banyak golf yang bisa dilakukan. Saya mengambil pass cepat jika dan turun ke 520 byte , yang seharusnya memberi Anda awal yang baik.
Shaggy
Tentunya beberapa penggantian + atob / btoa akan menghemat beberapa byte
Downgoat
1
@ Shaggy terima kasih banyak. Saya harus banyak belajar.
busur
Sama-sama :) Anda memiliki ruang nyasar s>6&&(yang selanjutnya dapat menghemat satu byte. Anda juga dapat menyimpan byte lain dengan mengganti (w=q+12)dengan w, repeat(q=i.length*9)dengan repeat(w=i.length*9)dan repeat(q)dengan repeat(w,w+=12).
Shaggy
9

Arang , 180 171 168 163 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

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

Cetak paranada.

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

Cetak kunci.

F⪪θ «

Ulangi setiap not.

A⌕AGFEDCbagfedc§ι¹λ

Temukan koordinat Y dari not tersebut.

JχλA⁺⁹χχ

Ini benar-benar licik: χadalah variabel yang sudah ditentukan ke 10, yang merupakan koordinat X dari not pertama, jika ada. Setelah melompat ke posisi itu, 9 ditambahkan ke dalamnya, mewakili posisi nada berikutnya.

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

Cetak yang tidak disengaja, jika ada.

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

Cetak garis besar buku jika perlu dan catatan. Faktanya, garis dicetak pada koordinat y apa pun walaupun mencetaknya di atas paranada tidak memiliki efek.

¿›ι2

Tidak ada lagi yang bisa dilakukan untuk semibreves.

¿›λ⁶«

Untuk catatan di bawah titik tengah,

↗↑⁴

gambar batang ke atas,

¿›ι8«↘↘¹↓¹

dan bendera untuk getaran.

»»«

Untuk catatan di atas titik tengah,

↙↓⁴

gambar batang ke bawah,

¿›ι8«↗↗¹↑¹

dan bendera untuk getaran.

Neil
sumber
Anda mengalahkan SOGL! :-)
Charlie
@CarlosAlejo saya berharap itu terjadi. Tapi saya memang berharap bisa mengalahkan saya dengan 20% juga.
dzaima
@dzaima mungkin jika itu adalah tantangan ASCII-art murni, tetapi yang ini juga memiliki bagian logika yang membuat output tergantung pada input. Meskipun demikian saya masih terbiasa dengan apa yang bisa dilakukan setiap bahasa dengan lebih baik.
Charlie