Ноти ASCII-арт-генератор


31

Примітка : Андерс Касеорг попереджає мене, що це може бути дублікатом іншого попереднього питання . Це здається, і мені дуже шкода, що я не знайшов цього питання перед тим, як опублікувати це. Тим не менш, на це питання було отримано лише одну відповідь, і ця більш проста, на всякий випадок, якщо ви все-таки захочете спробувати цього разу. Я зрозумію, якщо це питання в кінцевому підсумку буде позначено як дублікат.

Змагання

Враховуючи такий вхід:

8g 8Df 4cs 2C 1A

Напишіть найкоротшу програму / функцію, яка дає такий вихід:

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

Правила

Вихід повинен складатися з п'ятилінійного персоналу, який починається з малювання G-ключем точно так, як показано вище, вирівнюється зліва від штату та залишає одну колонку після початку роботи штату.

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

Нотатки повинні починатися з символу *або oсимволу залежно від його типу.

Має бути рівно вісім стовпців розділення кожного *або oсимволу:

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

Персонал повинен закінчуватися термінатором, вирівняним праворуч, як показано в прикладі. Лівий рядок термінатора повинен бути відокремлений 8 стовпцями від останньої ноти.

Вхід буде представляти собою один рядок, що містить нотатки (принаймні один, без порожніх входів), кожен розділений пробілом (ви можете вважати, що кожна примітка буде належною, тому не потрібно перевіряти на помилки). Ви також можете приймати введення як масив рядків із приміткою на елемент у масиві. Для кожної ноти перший символ буде знаменником довжини ноти ( 1для цілої ноти / напівкоси , починається з o; 2для половини нота / мінімуму , починається з o; 4для чверті нота / гачком , починається з *; і 8для восьмої примітка / тремтіння , починається з*). Другим символом буде нота (див. Наступну таблицю), а третій, необов’язковий символ, буде fабо Fдля плоских нотаток, sабо Sдля гострих нот.

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

Очевидно, що вхід повинен поважати регістр приміток, але ви можете вибрати регістр fі sмодифікаторів.

Примітки cі Aповинні додавати дві -(лінійки ведення книги), по одній з кожної сторони, оскільки вони повинні розширювати штат. Зауваження dта Gвийшли із співробітників , але не потребують в ГК лінії.

Вирівняні або загострені нотатки повинні містити bабо #дві позиції зліва від нотатки.

Стебла (якщо такі є) необхідно намалювати 4 вертикальними брусками. Нотатки bзверху і вище повинні бути намальовані стеблом вниз і в лівій частині ноти. Нотатки aзверху та знизу повинні малювати стебло вгору та в правій частині ноти. Квалівці повинні додавати прапор завжди праворуч і точно так, як показано, і їх не потрібно випромінювати, якщо їх є кілька підряд.

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

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

Як завжди, ваша програма / функція може безпосередньо намалювати вихідний сигнал або повернути рядок, масив рядків, матрицю символів або будь-який інший розумний формат.

Корисні посилання

Це , тому може виграти найкоротша програма / функція для кожної мови!

Бонус: спробуйте написати приклади з відомими мелодіями і нехай кожен спробує здогадатися, яка це мелодія!




... тож ми навіть не можемо скористатися випадком букви, щоб сказати, яким способом намалювати стебло?
Ніл

1
@Neil вибач, боюсь, ти не можеш. Я не склав цього правила, я перевірив, що "стебла зазвичай вказують на ноти середньої лінії або вище, а вгору - на ті, що нижче".
Чарлі

1
Чи можемо ми взяти масив рядків, кожен рядок - як одна примітка, як вхідний?
Shaggy

Відповіді:


13

SOGL V0.12 , 178 175 174 173 172 171 байт

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

Спробуйте тут! (θ додано для зручності використання; для запуску 171 байта очікується, що вхід буде в стеку)

Наскільки я можу сказати, це працює, але якщо ви знайдете якісь проблеми, скажіть мені.

Пояснення:

перша частина: створення полотна

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

друга частина: петля, помітка розміщення головки

{                        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

третя частина: прапори та стебла

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

Ваш код майже ідеальний. Єдина нітрик - це те, що 2bsу вашому прикладі нота повинна бути стержнем, спрямованою вниз.
Чарлі

@CarlosAlejo fix
dzaima

Чудово! І дякую за пояснення!
Чарлі

10

JavaScript (ES6), 616 527 байт

Дякуємо @shaggy за видалення майже 90 байт

Я не мав уявлення про замітки ... до цього часу, сподіваюся, що я все зрозумів.

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

пояснення

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``

Я думаю, що ви можете зберегти кілька байтів, заощадивши t[0]і t[2], а потім просто зробітьq=t.length*9
Стівен

2
Ласкаво просимо до PPCG. Дуже приємна перша відповідь :) Хоча можна зробити ще трохи гольфу, що можна зробити. Я швидко перейшов, якщо і скоротив його до 520 байт , що має добре почати.
Shaggy

Безумовно, що деякі заміни + atob / btoa врятують деякі байти
Downgoat

1
@Shaggy дуже дякую У мене є чому навчитися.
дуги

Вас вітає :) У вас є бродячий простір, після s>6&&(якого ви зможете заощадити байт. Ви також можете зберегти інший байт, замінивши (w=q+12)на w, repeat(q=i.length*9)з repeat(w=i.length*9)і repeat(q)на repeat(w,w+=12).
Shaggy

9

Вугілля деревне , 180 171 168 163 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

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

Роздрукуйте накладку.

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

Роздрукуйте ключик.

F⪪θ «

Проведіть через кожну замітку.

A⌕AGFEDCbagfedc§ι¹λ

Знайдіть координату Y примітки.

JχλA⁺⁹χχ

Це дійсно підступно: χце змінна, яка заздалегідь задана до 10, що є точно X-координатою випадкової ноти, якщо вона є. Після переходу до цієї позиції до нього додається 9, що представляє наступну позицію ноти.

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

Роздрукуйте випадково, якщо такий є.

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

При необхідності надрукуйте рядки книги та примітку. Насправді рядок друкується на будь-якій рівномірній координаті y, хоча надрукувати її на стінці, звичайно, не має ефекту.

¿›ι2

Більше нічого не можна зробити для напівкорів.

¿›λ⁶«

Для приміток нижче середини,

↗↑⁴

намалюйте стебло вгору,

¿›ι8«↘↘¹↓¹

і прапор для трепетів.

»»«

Для приміток вище середини,

↙↓⁴

намалюйте стебло вниз,

¿›ι8«↗↗¹↑¹

і прапор для трепетів.


Ви побили SOGL! :-)
Чарлі

@CarlosAlejo Я очікував, що це станеться. Але я очікував, що він також поб'є мене на 20%.
dzaima

@dzaima, можливо, якби це був чистий ASCII-арт-виклик, але в цьому також є логічна частина, яка робить висновок залежним від вхідних даних. Тим не менш, я все ще звикаю до того, що кожна мова може зробити краще.
Чарлі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.