Перетворення між музичними ключами


12

Перед тим, як піти, вам не потрібно розуміти музичну нотацію, щоб зробити цей виклик.

ПОЯСНЕННЯ

У стандартній ноті подвійні ключі переходять по всій сторінці, слугуючи орієнтирами до нот, повідомляючи про те, яку ноту слід відтворити. Якщо ви ще не знайомі з високим і басовим ключем, ось опис з Вікіпедії:

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

Ноти

На зображенні вище, у верхній половині рядків - високий ключ, позначений символом a Скрипкий ключик

Нижня половина - басовий ключ, позначений символом a Бас Клеф

Як ви можете бачити на скрипковий ключ запискою на самій нижній частині є E . (Я не рахуючи нот за межами CLEF ліній для цього завдання) На бас - ключах, найнижча лінія є G . Щоб виконати цей виклик, потрібно зробити наступне:

ВИКОНАННЯ

Давши введення в одній з наступних форм (на ваш вибір), перетворіть його на протилежний ключ. Будь то трендовий або бас-клаф може бути значенням Truthey / Falsey у вашій мові (не тільки будь-яких двох значень), наприклад

F # T або F # True або F # Treble

але не

F # -1 або F # 4

Пробіли та написання великих літер необов’язкові, квартири не відображатимуться, а пробіли пробілів заборонені.

Input          Expected Output
E   Treble     G
F   Treble     A
F#  Treble     A#
G   Treble     B
G#  Treble     C
A   Treble     C
A#  Treble     C#
B   Treble     D
C   Treble     E
C#  Treble     F
D   Treble     F
D#  Treble     F#
E   Treble     G
F   Treble     A
F#  Treble     A#
G   Bass       E
G#  Bass       F
A   Bass       F
A#  Bass       F#
B   Bass       G
C   Bass       A
C#  Bass       A#
D   Bass       B
D#  Bass       C
E   Bass       C
F   Bass       D
F#  Bass       D#
G   Bass       E
G#  Bass       F
A   Bass       F
A#  Bass       F#

Попереджуйте, це не тривіальна проблема постійної різниці. Подивіться уважно на входи та виходи. Якщо ви дивитесь на фортепіано,

Фортепіано

чорні клавіші різкі, позначені символом #. Зверніть увагу, що немає E # або B #. Це означає, що якщо вам задано G # на ключі Bass, замість повернення E # , вам потрібно повернути F

Це , тому виграє найменший байт.


1
Чи треба турбуватися про квартири? Як щодо подвійних квартир / гостриків?
mypetlion

1
Будь ласка, не створюйте теги для тем, які не гарантують їх.
Джонатан Аллан

3
Чи добре нормально пробільний пробіл (повернення C замість C)?
Лінн

2
Чи дозволено використання 1та -1(або навіть сказати 4і -4) для введення індикатора ключа або це буде прийнятним лише у тому випадку, якщо вони мають значення truthy / falsey нашої мови?
Джонатан Аллан

1
Це приємний і добре представлений виклик, але було б ще краще ІМО із злегка розслабленими форматами введення / виведення.
Арнольд

Відповіді:


5

Желе ,  35  34 байт

У мене є відчуття, що деяка арифметика може перемогти цей метод.

ØAḣ7µW€ż;€”#$Ẏ
Ç”C4¦”F⁵¦
Ñi+_⁸?4ị¢

Спробуйте в Інтернеті!

Повна програма з 1) індикатором clef 0або відповідно 1для Bass або Treble і 2) нота; та друк отриманої ноти.

Було б 31 байт, якби -4і 4були прийнятними як вхідні значення індикатора ключа (тоді вони Ñi+_⁸?4ị¢можуть стати Ñi+⁸ị¢), але це було уточнено як недозволене, якщо -4 не є фальсією і 4 - правдою, що не стосується Jelly.

Як?

Будує клавіатуру з фантомом B#та E#клавішами, знаходить індекс введення, зміщує, що 4в потрібному напрямку, індексує назад на клавіатуру, а ті фантомні клавіші замінюються на необхідні результати (клавіша над ними):

ØAḣ7µW€ż;€”#$Ẏ - Link 1, keyboard with phantoms: no inputs
ØA             - alphabet yield        -> ['A', 'B', ..., 'Z']
   7           - literal seven
  ḣ            - head                  -> ['A','B','C','D','E','F','G']
    µ          - new monadic chain, call that K
     W€        - wrap €ach             -> ["A","B","C","D","E","F","G"] ("" being lists of characters)
            $  - last two links as a monad:
          ”#   -   character '#'
        ;€     -   concatenate to €ach -> ["A#","B#","C#","D#","E#","F#","G#"]
       ż       - zip together          -> [["A","A#"],["B","B#"],["C","C#"],["D","D#"],["E","E#"],["F","F#"],["G","G#"]]
             Ẏ - tighten               -> ["A","A#","B","B#","C","C#","D","D#","E","E#","F","F#","G","G#"]

Ç”C4¦”F⁵¦ - Link 2, keyboard with phantoms replaced: no inputs
Ç         - call the last link (1) as a monad  ["A","A#","B","B#","C","C#","D","D#","E","E#","F","F#","G","G#"]
    ¦     - sparse application:
   4      - ...to index: literal four
 ”C       - ...action: character 'C'    -> ["A","A#","B","C","C","C#","D","D#","E","E#","F","F#","G","G#"]
        ¦ - sparse application:
       ⁵  - ...to index: literal ten
     ”F   - ...action: character 'F'    -> ["A","A#","B","C","C","C#","D","D#","E","F","F","F#","G","G#"]

Ñi+_⁸?4ị¢ - Main link: integer, clef (1 Treble / 0 Bass); list of characters, key
                                      e.g. 0; "D#"
Ñ         - next link (1) as a monad (no atom for next link as a nilad, but this works here anyway)
          -                               ["A","A#","B","B#","C","C#","D","D#","E","E#","F","F#","G","G#"]
 i        - first index of key in that    8
      4   - literal four
     ?    - if:
    ⁸     - ...condition: chain's left argument, clef
  +       - ...then: addition
   _      - ...else: subtraction          4
        ¢ - next link as a nilad          ["A","A#","B","C","C","C#","D","D#","E","F","F","F#","G","G#"]
       ị  - index into                    "C"

Зелена перевірка: Хм, так що ніхто ще не переміг цей бал - я досить шокований.
Джонатан Аллан

9

Befunge, 70 64 байт

~0~:70p##~+2%00p+"A"-~7%2++7%:3%2%00g*:10p+"A"+,00g!10g+#@_"#",@

Спробуйте в Інтернеті!

Вхід має бути у формі C# Trebleабо F Bass, хоча ключ може бути просто першою літерою (тобто Tабо B), оскільки решта входу все одно ігнорується.

Пояснення

~0        Read the note and push a zero (the purpose of this will become apparent later).
~:70p     Read the following sharp or space and write that out as the next instruction.

У результаті цієї модифікації коду наступна послідовність інструкцій матиме одну з двох форм:

##~       The first # jumps over the second, and thus we perform the read instruction.
 #~       But if there's only one #, we'll ending up skipping the read instruction.

У цей момент стек або містить, note,0,sharp,spaceабо note,0,space.

+2%       Add the top two stack items mod 2, returning 1 if we read a sharp, else 0 if not.
00p       Save this 'sharp' boolean for later use.

У цей момент стек або містить, note,0або просто note(із неявним нулем внизу).

+         By adding the top two items, we combine the 0 (if present) onto the note below.
"A"-      We can then subtract 'A' to convert the note into a number in the range 0 to 6.
~7%2+     Read the T/B clef, then mod 7 and add 2, returning 2 or 5 (the conversion offset).
+7%       Add that offset to our note number, then mod 7, to get the converted note number.
:3%2%     Make a dup, and calculate mod 3 mod 2 to determine the special cases (B# or E#).
00g*      Multiply that by the 'sharp' boolean, since we only care if the input was sharp.
:10p      Duplicate and save this special case boolean for later.
+         Now add it to the note number, since the special cases need to be offset by 1.
"A"+,     Then we can finally convert the number back into a character and output it.
00g!10g+  Now we check if the original note was not sharp, or if this was a special case.
#@_       If so, we exit immediately.
"#",@     Otherwise, we output a '#'.


3

JavaScript (ES6) 74 байти

Приймає вхідний сигнал в вичинки синтаксису , (note)(clef)де clefє 0для баса і 1для високих частот .

n=>c=>'FC.DAFCGDAEBF'[k=(parseInt(n,36)*15+!n[1]*90+c)%98%13]+(k<5?'#':'')

Демо

Як?

Це насправді трохи менш весело, ніж моя попередня версія, але основна таблиця пошуку тепер F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fдозволяє скоротити # умову, уникаючи при цьому символу трюку символів NUL - це, напевно, було трохи межею.


Попередня версія 76 75 байт

n=>c=>'ACCDFF.CDEFGABCDE'[k=parseInt(4*!!n[1]+c+n,21)%24%17]+'\0#'[45>>k&1]

Демо

Як?

Вхід (n, c) обробляється за допомогою наступних кроків:

  1. Спочатку ми оцінюємо, 4 * !!n[1] + c + nде !!n[1]відповідає істині (примусово до 1 ), якщо примітка містить # , а неправді (примусово до 0 ) в іншому випадку. Вираз 4 * !!n[1] + cпризводить до числового значення, яке додається перед рядком n .

  2. Неявний крок: провідні нулі та кінцевий номер # ігноруються parseInt(). Наприклад, "5G#"насправді аналізується як "5G".

  3. Ми перетворюємо новий рядок у десяткове значення, аналізуючи його як величину-21.

  4. Застосовуємо модуль 24.

  5. Застосовуємо модуль 17.

Нижче наведена підсумкова таблиця для всіх можливих пар вводу, а також очікуваний вихід. Зауважте, що до результату потрібно додати #, якщо кінцевий результат дорівнює 0 , 2 , 3 або 5 . Отже, використання двійкової маски 101101 ( 45 в десятковій частині).

 n   | c | (1)   | (2)   | (3) | (4) | (5) | Output
-----+---+-------+-------+-----+-----+-----+-------
"E"  | 1 | "1E"  | "1E"  |  35 |  11 |  11 | "G"
"F"  | 1 | "1F"  | "1F"  |  36 |  12 |  12 | "A"
"F#" | 1 | "5F#" | "5F"  | 120 |   0 |   0 | "A#"
"G"  | 1 | "1G"  | "1G"  |  37 |  13 |  13 | "B"
"G#" | 1 | "5G#" | "5G"  | 121 |   1 |   1 | "C"
"A"  | 1 | "1A"  | "1A"  |  31 |   7 |   7 | "C"
"A#" | 1 | "5A#" | "5A"  | 115 |  19 |   2 | "C#"
"B"  | 1 | "1B"  | "1B"  |  32 |   8 |   8 | "D"
"C"  | 1 | "1C"  | "1C"  |  33 |   9 |   9 | "E"
"C#" | 1 | "5C#" | "5C"  | 117 |  21 |   4 | "F"
"D"  | 1 | "1D"  | "1D"  |  34 |  10 |  10 | "F"
"D#" | 1 | "5D#" | "5D"  | 118 |  22 |   5 | "F#"
-----+---+-------+-------+-----+-----+-----+-------
"E"  | 0 | "0E"  | "E"   |  14 |  14 |  14 | "C"
"F"  | 0 | "0F"  | "F"   |  15 |  15 |  15 | "D"
"F#" | 0 | "4F#" | "4F"  |  99 |   3 |   3 | "D#"
"G"  | 0 | "0G"  | "G"   |  16 |  16 |  16 | "E"
"G#" | 0 | "4G#" | "4G"  | 100 |   4 |   4 | "F"
"A"  | 0 | "0A"  | "A"   |  10 |  10 |  10 | "F"
"A#" | 0 | "4A#" | "4A"  |  94 |  22 |   5 | "F#"
"B"  | 0 | "0B"  | "B"   |  11 |  11 |  11 | "G"
"C"  | 0 | "0C"  | "C"   |  12 |  12 |  12 | "A"
"C#" | 0 | "4C#" | "4C"  |  96 |   0 |   0 | "A#"
"D"  | 0 | "0D"  | "D"   |  13 |  13 |  13 | "B"
"D#" | 0 | "4D#" | "4D"  |  97 |   1 |   1 | "C"

3

Python 2 , 77 байт

Функція, на яку друкується STDOUT. Trueперетворює баси в високі, і Falseперетворює високі в баси.

def f(n,c):N=ord(n[0])-63-4*c;M=-~N%3<1<len(n);print chr((N+M)%7+65)+n[1:2-M]

Спробуйте в Інтернеті!

Пояснення:

  • Перше твердження N=ord(n[0])-63-4*c;обчислює індекс (0 до 7) листа нової ноти, не враховуючи різких різкостей.
    • ord(N[0])-63-4*cотримує індекс поточної літери та додає або віднімає 2 залежно від значення c(змінна для переключення напрямку перетворення)
  • Наступне твердження M=-~N%3<1<len(n);обчислює, чи потрібно цю змінну коригувати чи ні. Наприклад, якщо нова нота є E, а оригінальна нота була різкою, це потрібно буде відкоригувати на " F. Ланцюгова нерівність працює так:
    • -~N%3<1перевіряє, чи відповідає індекс ноти нотатки в послідовності 3n-1. Це буде тільки вихід вірно для Eі B, дві ноти , які не мають різкий.
    • 1<len(n)перевіряє, чи оригінальна нота була різкою (це зробило б довжину рядка більше 1). Це необхідно, оскільки, якби не було різкого, немає необхідності коригувати нові ноти.
    • Це встановлює значення Mабо Trueабо False, яке може бути використане в обчисленні як 1і 0відповідно, тому для виконання коригування нам потрібно лише додати M до N, а модуль - 7.
  • Підсумкове твердження створює та виводить кінцевий результат.
    • chr((N+M)%7+65) додає коригування, якщо необхідно, потім перетворює значення з індексу назад в символ.
    • +n[1:2-M]додасть гострий символ, якщо обидва M=0(корегування не було зроблено) і початкове значення також мали різке.

1
Вибачте, лише 0 і 1, Truthey & Falsey або T&B
FantaC

@tfbninja дякую за уточнення
FlipTack

2

Java 8, 119 байт

n->b->(b?"C D E F G A B C# F F# A# C":"F G A B C D E F# A# C D# F").split(" ")["A B C D E F G A#C#D#F#G#".indexOf(n)/2]

Пояснення:

Спробуйте тут.

n->b->         // Method with String and boolean parameters and String return-type
  (b?          //  If it's Treble:
    "C D E F G A B C# F F# A# C"
               //   Use this String
   :           //  Else (it's Bass):
    "F G A B C D E F# A# C D# F")
               //   Use this String
  .split(" ")  //  Split this String by spaces,
   [           //  and then get the item at index:
    "A B C D E F G A#C#D#F#G#".indexOf(n)
               //   Get the index of the String on the left,
    /2]        //   and divide this by 2
               // End of method (implicit / single-line return-statement)

1
ще одне рішення з 99 байтами:n->b->((char)((n.charAt(0)-(b?0:4))%7+65)+n.substring(1)).replaceAll("B#","C").replaceAll("E#","F")
Nahuel Fouilleul

@NahuelFouilleul Ах приємно! Я справді думав щось із чарівним складом, а якийсь модуль може бути коротшим. Але оскільки вона трохи відрізняється від моєї нинішньої відповіді, сміливо розміщуйте її як окрему відповідь. Ви отримаєте мою нагороду, якщо ви це зробите. :)
Кевін Круїссен

0

R , 111 байт

function(k,C,N=paste0(LETTERS[2:15%/%2],c("","#")))sub("E#","F",sub("B#","C",N[which(k==N[(4:17+6*C)%%14+1])]))

Спробуйте в Інтернеті!

Безголівки:

function(k,C){
  N=paste0(LETTERS[2:15%/%2],c("","#")) # Generate a vector of the notes, including E# and B#
  M=N[(4:17+6*C)%%14+1])                # Create a copy that's cycled either up 4 or down 4
  P=N[which(k==M)]                      # Look up the input note in the complementary vector
  P=sub("B#","C",P)                     # Replace B# with C
  P=sub("E#","F",P)                     # Replace E# with F
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.