Convertir entre claves de música

12

Antes de partir, no tiene que entender mucha notación musical para hacer este desafío.

EXPLICACIÓN

En la partitura estándar, las claves dobles atraviesan la página y sirven como puntos de referencia para las notas, lo que le permite saber qué nota debe reproducirse. Si aún no está familiarizado con la clave de agudos y bajos, aquí hay una descripción de Wikipedia:

Una clave es un símbolo musical utilizado para indicar el tono de las notas escritas. Colocado en una de las líneas al comienzo del pentagrama, indica el nombre y el tono de las notas en esa línea. Esta línea sirve como un punto de referencia por el cual se pueden determinar los nombres de las notas en cualquier otra línea o espacio del pentagrama.

Partitura

En la imagen de arriba, la mitad superior de las líneas es la clave de sol, denotada con un Clave de sol

La mitad inferior es la clave de bajo, denotada con un Clave de fa

Como se puede ver en la clave de sol una nota en la parte inferior-line más es una E . (No estoy contando notas fuera de las líneas agudo por este desafío) En la clave de fa, la línea más baja es un G . Para completar este desafío, debe hacer lo siguiente:

DESAFÍO

Dada una entrada en una de las siguientes formas (su elección), conviértala a la clave opuesta. Si se trata de la clave de sol o de graves, puede ser un valor de Truthey / Falsey en su idioma (no solo dos valores), p. Ej.

F # T o F # Verdadero o F # Agudos

pero no

F # -1 o F # 4

Los espacios y las mayúsculas son opcionales, los planos no aparecerán y no se permiten espacios en blanco al final.

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#

Tenga cuidado, este no es un desafío trivial de diferencia constante. Mire de cerca las entradas y salidas. Si miras un piano,

Piano

las teclas negras son punzantes, denotadas por #. Tenga en cuenta que no hay un E # o un B #. Esto significa que si recibe G # en la clave de graves, en lugar de devolver E # , debe devolver F

Este es el , por lo que gana el número más pequeño de bytes.

FantaC
fuente
1
¿Tenemos que preocuparnos por los pisos? ¿Qué tal pisos dobles / objetos punzantes?
mypetlion
1
No cree etiquetas para temas que no lo justifiquen.
Jonathan Allan
3
¿El espacio en blanco al final (en C lugar de C) está bien?
Lynn
2
¿Se permite usar 1y -1(o incluso decir, 4y -4) para la entrada del indicador de clave o esto solo sería aceptable si son valores de verdad / falsey en nuestro idioma?
Jonathan Allan
1
Este es un desafío agradable y bien presentado, pero hubiera sido aún mejor IMO con formatos de entrada / salida ligeramente relajados.
Arnauld

Respuestas:

5

Jalea ,  35  34 bytes

Tengo la sensación de que algo de aritmética puede ganar sobre este método.

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

Pruébalo en línea!

Un programa completo que toma 1) el indicador de clave 0o 1para graves o agudos respectivamente y 2) la nota; e imprimir la nota resultante.

Sería 31 bytes si -4y 4fuera aceptable como los valores de entrada del indicador de clave (entonces Ñi+_⁸?4ị¢pueden convertirse Ñi+⁸ị¢), pero esto se ha aclarado como no permitido a menos que -4 sea falso y 4 sea verdadero, que no es el caso para Jelly.

¿Cómo?

Construye un teclado con fantasma B#y E#teclas, encuentra el índice de la entrada, compensa que, 4en la dirección requerida, indexa nuevamente en un teclado con esas teclas fantasmas reemplazadas por sus resultados requeridos (la tecla encima de ellas):

Ø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"
Jonathan Allan
fuente
Verificación verde: Hmm, así que nadie ha superado este puntaje, estoy bastante sorprendido.
Jonathan Allan
9

Befunge, 70 64 bytes

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

Pruébalo en línea!

La entrada debe estar en forma C# Trebleo F Bass, aunque la clave puede ser simplemente la primera letra (es decir, To B), ya que el resto de la entrada se ignora de todos modos.

Explicación

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

Como resultado de esta modificación del código, la siguiente secuencia de instrucciones tomará una de dos formas:

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

En este punto, la pila contiene note,0,sharp,spaceo 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.

En este punto, la pila contiene note,0o simplemente note(con un cero implícito a continuación).

+         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 '#'.
James Holderness
fuente
3

Perl 5, 56 bytes

$_=<>;s/./chr 65+(-4*<>+ord$&)%7/e;s/B#/C/;s/E#/F/;print

Lee la nota y la clave como dos líneas de STDIN e imprime la nueva nota en STDOUT. La clave es 0para agudos y 1bajos.

faubi
fuente
1
puede guardar 11 bytes usando el -pindicador tio.run/##K0gtyjH9/79YX08/OaNIwcxUW0PXRMvGTju/KEVFTVPVXD/…
Nahuel Fouilleul el
3

JavaScript (ES6) 74 bytes

Toma de entrada en la sintaxis Zurra de (note)(clef)donde clefes 0para el bajo y 1para agudos .

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

Manifestación

¿Cómo?

En realidad, esto es un poco menos divertido que mi versión anterior, pero la tabla de búsqueda subyacente ahora F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fpermite acortar la condición # mientras se evita el truco de caracteres NUL , que suponía que era un poco marginal.


Versión anterior 76 75 bytes

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

Manifestación

¿Cómo?

La entrada (n, c) se procesa mediante los siguientes pasos:

  1. Primero evaluamos 4 * !!n[1] + c + ndónde !!n[1]es verdadero (forzado a 1 ) si la nota contiene un # , y falso (forzado a 0 ) de lo contrario. La expresión 4 * !!n[1] + cda como resultado un valor numérico que se agrega delante de la cadena n .

  2. Paso implícito: los ceros iniciales y los # finales son ignorados por parseInt(). Por ejemplo, en "5G#"realidad se analiza como "5G".

  3. Convertimos la nueva cadena a un valor decimal analizándola como una cantidad de base 21.

  4. Aplicamos el módulo 24.

  5. Aplicamos el módulo 17.

A continuación se muestra la tabla de resumen para todos los pares de entrada posibles, junto con la salida esperada. Tenga en cuenta que se debe agregar un # a la salida si el resultado final es 0 , 2 , 3 o 5 . De ahí el uso de la máscara binaria 101101 ( 45 en decimal).

 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"
Arnauld
fuente
3

Python 2 , 77 bytes

Función que imprime a STDOUT. Trueconvierte los graves a agudos y los Falseagudos a 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]

Pruébalo en línea!

Explicación:

  • La primera declaración, N=ord(n[0])-63-4*c;calcula el índice (0 a 7) de la carta de la nueva nota, sin tener en cuenta los objetos punzantes.
    • ord(N[0])-63-4*cobtiene el índice de la letra actual y suma o resta 2 dependiendo del valor de c(variable para alternar la dirección de conversión)
  • La siguiente declaración, M=-~N%3<1<len(n);calcula si esta variable tendrá que ajustarse o no. Por ejemplo, si la nueva nota es Ey la nota original tenía una nitidez, será necesario ajustarla a F. La desigualdad encadenada funciona de la siguiente manera:
    • -~N%3<1comprueba si el índice de la nueva nota está en la secuencia 3n-1. Esto solo dará verdadero para Ey B, las dos notas que no tienen un fuerte.
    • 1<len(n)comprueba si la nota original tenía una nitidez (esto haría que la longitud de la cuerda fuera mayor que 1). Esto es necesario ya que, si no hubo nitidez, no hay necesidad de ajustar las nuevas letras de nota.
    • Esto establece el valor de Mcualquiera Trueo False, que se puede usar en el cálculo como 1y 0respectivamente, por lo que para realizar el ajuste solo necesitamos agregar M a N y módulo por 7.
  • La declaración final crea y genera el resultado final.
    • chr((N+M)%7+65) agrega el ajuste si es necesario, luego convierte el valor de un índice a un carácter.
    • +n[1:2-M]agregará un símbolo agudo si tanto M=0(no se realizó ningún ajuste) como el valor original también tenían un fuerte.
FlipTack
fuente
1
Lo sentimos, solo 0 y 1, Truthey y Falsey, o T&B
FantaC
@tfbninja gracias por la aclaración
FlipTack
2

Java 8, 119 bytes

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]

Explicación:

Pruébalo aquí.

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)
Kevin Cruijssen
fuente
1
Otra solución con 99 bytes:n->b->((char)((n.charAt(0)-(b?0:4))%7+65)+n.substring(1)).replaceAll("B#","C").replaceAll("E#","F")
Nahuel Fouilleul, el
@NahuelFouilleul ¡Ah, qué bien! De hecho, estaba pensando en algo con un reparto de personajes y algún módulo podría ser más corto. Pero como es un poco diferente de mi respuesta actual, siéntase libre de publicarla como una respuesta separada. Tienes mi voto a favor si lo haces. :)
Kevin Cruijssen
0

R , 111 bytes

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

Pruébalo en línea!

Sin 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
}
usuario2390246
fuente