Conversion entre clés de musique


12

Avant de partir, vous n'avez pas besoin de comprendre beaucoup de notation musicale pour relever ce défi.

EXPLICATION

Dans les partitions standard, les doubles clés traversent la page et servent de points de référence aux notes, vous permettant de savoir quelle note doit être jouée. Si vous n'êtes pas déjà familier avec la clé de sol et de basse, voici une description de Wikipedia:

Une clef est un symbole musical utilisé pour indiquer la hauteur des notes écrites. Placé sur l'une des lignes au début de la portée, il indique le nom et la hauteur des notes sur cette ligne. Cette ligne sert de point de référence par lequel les noms des notes sur toute autre ligne ou espace de la portée peuvent être déterminés.

Partition

Dans l'image ci-dessus, la moitié supérieure des lignes est la clé de sol, notée d'un Clé de sol

La moitié inférieure est la clef de basse, notée d'un Clef de basse

Comme vous pouvez le voir sur les aigus sur une note clé le plus bas en ligne est un E . (Je ne compte pas les notes en dehors des lignes pour ce défi clef) Sur la clef basse, la ligne la plus basse est un G . Pour relever ce défi, vous devez procéder comme suit:

DÉFI

Étant donné une entrée sous l'une des formes suivantes (votre choix), convertissez-la en clé opposée. Que ce soit la clé de sol ou la clé de basse peut être une valeur Truthey / Falsey dans votre langue (pas seulement deux valeurs), par exemple

F # T ou F # True ou F # Treble

mais non

F # -1 ou F # 4

Les espaces et les majuscules sont facultatifs, les plats n'apparaissent pas et les espaces de fin ne sont pas autorisés.

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#

Soyez prévenu, ce n'est pas un défi trivial de différence constante. Regardez attentivement les entrées et les sorties. Si vous regardez un piano,

Piano

les touches noires sont tranchantes, désignées par #. Notez qu'il n'y a ni E # ni B #. Cela signifie que si on vous donne G # sur la clé de basse, au lieu de retourner E # , vous devez retourner F

Il s'agit de , donc le plus petit nombre d'octets gagne.


1
Faut-il se soucier des appartements? Que diriez-vous des appartements doubles / tranchants?
mypetlion

1
Veuillez ne pas créer de balises pour des sujets qui ne les justifient pas.
Jonathan Allan

3
Est-ce que les espaces vides (retournant à la C place de C) vont bien?
Lynn

2
L'utilisation de 1et -1(ou même de dire, 4et -4) pour l'entrée d'indicateur de clé est-elle autorisée ou serait-ce acceptable uniquement s'il s'agit de valeurs véridiques / falsey dans notre langue?
Jonathan Allan

1
C'est un défi agréable et bien présenté, mais cela aurait été encore mieux IMO avec des formats d'entrée / sortie légèrement détendus.
Arnauld

Réponses:


5

Gelée ,  35  34 octets

J'ai le sentiment qu'un peu d'arithmétique pourrait gagner cette méthode.

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

Essayez-le en ligne!

Un programme complet prenant respectivement 1) l'indicateur de clé 0ou 1pour Bass ou Treble et 2) la note; et imprimer la note résultante.

Serait de 31 octets si -4et 4étaient acceptables comme valeurs d'entrée de l'indicateur de clé ( Ñi+_⁸?4ị¢peuvent alors devenir Ñi+⁸ị¢) mais cela a été clarifié comme non autorisé à moins que -4 soit falsey et 4 soit véridique, ce qui n'est pas le cas pour Jelly.

Comment?

Construit un clavier avec fantôme B#et E#touches, trouve l'index de l'entrée, compense que par 4dans la direction requise, indexe de nouveau dans un clavier avec ces touches fantômes remplacées par leurs résultats requis (la touche au-dessus d'eux):

Ø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"

Green check: Hmm, donc personne n'a encore battu ce score - je suis assez choqué.
Jonathan Allan

9

Befunge, 70 64 octets

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

Essayez-le en ligne!

L'entrée doit être sous la forme C# Trebleou F Bass, bien que la clé puisse simplement être la première lettre (c'est T-à- dire ou B), car le reste de l'entrée est de toute façon ignoré.

Explication

~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.

À la suite de cette modification de code, la prochaine séquence d'instructions prendra l'une des deux formes suivantes:

##~       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.

À ce stade, la pile contient note,0,sharp,spaceou 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.

À ce stade, la pile contient note,0ou juste note(avec un zéro implicite ci-dessous).

+         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 octets

Prend entrée dans la syntaxe curryfication (note)(clef)clefest 0pour la basse et 1des aigus .

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

Démo

Comment?

C'est en fait un peu moins amusant que ma version précédente, mais la table de recherche sous-jacente est maintenant F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fce qui permet de raccourcir la condition # tout en évitant l' astuce de caractère NUL - qui était un peu limite, je suppose.


Version précédente 76 75 octets

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

Démo

Comment?

L'entrée (n, c) est traitée par les étapes suivantes:

  1. Nous évaluons d'abord 4 * !!n[1] + c + n!!n[1]est vrai (contraint à 1 ) si la note contient un # , et faux (contraint à 0 ) sinon. L'expression 4 * !!n[1] + cdonne une valeur numérique qui est ajoutée devant la chaîne n .

  2. Étape implicite: les zéros de tête et les # de fin sont ignorés par parseInt(). Par exemple, "5G#"est en fait analysé comme "5G".

  3. Nous convertissons la nouvelle chaîne en une valeur décimale en l'analysant comme une quantité de base 21.

  4. Nous appliquons modulo 24.

  5. Nous appliquons modulo 17.

Vous trouverez ci-dessous le tableau récapitulatif de toutes les paires d'entrées possibles, ainsi que la sortie attendue. Notez qu'un # doit être ajouté à la sortie si le résultat final est 0 , 2 , 3 ou 5 . D'où l'utilisation du masque binaire 101101 ( 45 en décimal).

 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 octets

Fonction qui imprime vers STDOUT. Trueconvertit les graves en aigus et Falseconvertit les aigus en graves.

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]

Essayez-le en ligne!

Explication:

  • La première instruction,, N=ord(n[0])-63-4*c;calcule l'indice (0 à 7) de la lettre de la nouvelle note, sans tenir compte des objets tranchants.
    • ord(N[0])-63-4*cobtient l'index de la lettre actuelle et ajoute ou soustrait 2 selon la valeur de c(variable pour basculer dans le sens de la conversion)
  • L'instruction suivante M=-~N%3<1<len(n);calcule si cette variable devra ou non être ajustée. Par exemple, si la nouvelle note est E, et la note d'origine avait une forte, cela devra être ajusté à un F. L'inégalité chaînée fonctionne comme suit:
    • -~N%3<1vérifie si l'index de la nouvelle note est dans la séquence 3n-1. Cela ne donnera que vrai pour Eet B, les deux notes qui n'ont pas de forte.
    • 1<len(n)vérifie si la note d'origine avait une forte (ce qui rendrait la longueur de la chaîne supérieure à 1). Cela est nécessaire car, s'il n'y avait pas de netteté, il n'est pas nécessaire d'ajuster les nouvelles lettres de note.
    • Cela définit la valeur de Mà soit Trueou False, qui peut être utilisé dans le calcul comme 1et 0respectivement, donc pour effectuer l'ajustement, il suffit d'ajouter M à N et modulo par 7.
  • L'instruction finale crée et génère le résultat final.
    • chr((N+M)%7+65) ajoute l'ajustement si nécessaire, puis reconvertit la valeur d'un index en caractère.
    • +n[1:2-M]ajoutera un symbole pointu si les deux M=0(aucun ajustement n'a été effectué) et la valeur d'origine avaient également une valeur pointue.

1
Désolé, seulement 0 & 1, Truthey & Falsey, ou T&B
FantaC

@tfbninja merci pour la clarification
FlipTack

2

Java 8, 119 octets

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]

Explication:

Essayez-le ici.

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
une autre solution avec 99 octets:n->b->((char)((n.charAt(0)-(b?0:4))%7+65)+n.substring(1)).replaceAll("B#","C").replaceAll("E#","F")
Nahuel Fouilleul

@NahuelFouilleul Ah sympa! Je pensais en effet à quelque chose avec un casting de caractères et certains modulo pourraient être plus courts. Mais comme elle est un peu trop différente de ma réponse actuelle, n'hésitez pas à la poster en tant que réponse distincte. Vous avez mon vote positif si vous le faites. :)
Kevin Cruijssen

0

R , 111 octets

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])]))

Essayez-le en ligne!

Non golfé:

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
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.