Ноты 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и снизу должны нарисовать стебель вверх и с правой стороны банкноты. Quavers должен добавить флаг, всегда направо и точно так, как показано, и не должен быть передан, если их несколько в ряду.

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

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

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

Полезные ссылки

Это , поэтому может выиграть самая короткая программа / функция для каждого языка!

Бонус: попробуйте написать примеры с известными мелодиями, и пусть каждый попытается угадать, какая это мелодия!

Чарли
источник
Песочница .
Чарли
Дублирование?
Андерс Касеорг
... так что мы даже не можем использовать регистр букв, чтобы сказать, каким образом нарисовать стебель?
Нил
1
@ Не извините, боюсь, вы не можете. Я не составлял это правило, я проверил это : «Стебли обычно указывают вниз для нот на средней линии или выше, и вверх для тех, что ниже».
Чарли
1
Можем ли мы взять массив строк, где каждая строка представляет собой одну заметку, в качестве входных данных?
Лохматый

Ответы:

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
dzaima
источник
Ваш код почти идеален. Единственный придирка в том, что нота 2bsв вашем примере должна иметь ножку, направленную вниз.
Чарли
@CarlosAlejo исправлено
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 байт , что должно дать вам хорошее начало.
Лохматый
Конечно, некоторые замены + atob / btoa сохранят несколько байтов
Downgoat
1
@ Шэгги, большое спасибо. У меня есть чему поучиться.
дуги
Не за что :) У вас есть свободное место, после s>6&&(которого вы можете сэкономить байт. Вы также можете сохранить другой байт с помощью замены (w=q+12)на w, repeat(q=i.length*9)с repeat(w=i.length*9)и repeat(q)с repeat(w,w+=12).
Лохматый
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«↗↗¹↑¹

и флаг для кваверов.

Нил
источник
Вы победили СОГЛ! :-)
Чарли
@CarlosAlejo Я ожидал, что это произойдет. Но я ожидал, что это также побьет меня на 20%.
Дзайма
@dzaima, может быть, если бы это было чисто ASCII-искусство, но в этом также есть логическая часть, которая делает вывод зависимым от ввода. Тем не менее я все еще привыкаю к ​​тому, что каждый язык может делать лучше.
Чарли