Converti tra chiavi di musica


12

Prima di partire, non devi capire molta notazione musicale per fare questa sfida.

SPIEGAZIONE

Negli spartiti standard, le doppie chiavi vanno attraverso la pagina fungendo da punti di riferimento alle note, per farti sapere quale nota deve essere suonata. Se non hai già familiarità con la chiave di violino e basso, ecco una descrizione da Wikipedia:

Una chiave è un simbolo musicale usato per indicare l'altezza delle note scritte. Posizionato su una delle linee all'inizio del pentagramma, indica il nome e l'intonazione delle note su quella linea. Questa linea funge da punto di riferimento in base al quale è possibile determinare i nomi delle note su qualsiasi altra linea o spazio del pentagramma.

Spartito

Nell'immagine sopra, la metà superiore delle linee è la chiave di violino, indicata con a Chiave di violino

La metà inferiore è la chiave di basso, indicata con a Chiave di basso

Come si può vedere sulla chiave di violino una nota sul fondo più-line è un E . (Non sto contando note al di fuori delle linee di chiave di questa sfida) Sulla chiave di basso, la linea più basso è un G . Per completare questa sfida, è necessario effettuare le seguenti operazioni:

SFIDA

Dato un input in una delle seguenti forme (a tua scelta), convertilo nella chiave opposta. Che si tratti della chiave di violino o di basso, può essere un valore di Truthey / Falsey nella tua lingua (non solo due valori), ad es.

F # T o F # True o F # Treble

ma no

F # -1 o F # 4

Gli spazi e le maiuscole sono opzionali, gli appartamenti non verranno visualizzati e gli spazi bianchi finali non sono consentiti.

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#

Attenzione, questa non è una banale sfida a differenza costante. Osserva attentamente gli ingressi e le uscite. Se guardi un piano,

Pianoforte

i tasti neri sono appuntiti, indicati da #. Nota che non c'è un E # o un B #. Ciò significa che se ti viene dato G # sulla chiave di Bass, invece di restituire E # , devi restituire F

Questo è , quindi vince il conteggio dei byte più piccolo.


1
Dobbiamo preoccuparci degli appartamenti? Che ne dici di doppi appartamenti / oggetti taglienti?
mypetlion il

1
Si prega di non creare tag per argomenti che non li giustificano.
Jonathan Allan,

3
Va bene lo spazio bianco finale (che ritorna C invece di C)?
Lynn,

2
L'uso 1e -1(o addirittura dire, 4e -4) per l'input dell'indicatore chiave è consentito o sarebbe accettabile solo se sono valori di verità / falsità nella nostra lingua?
Jonathan Allan,

1
Questa è una sfida piacevole e ben presentata, ma sarebbe stata ancora meglio IMO con formati di input / output leggermente rilassati.
Arnauld,

Risposte:


5

Gelatina ,  35  34 byte

Ho la sensazione che un po 'di aritmetica possa vincere questo metodo.

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

Provalo online!

Un programma completo che prende 1) l'indicatore di chiave 0o rispettivamente 1per Bass o Treble e 2) la nota; e stampare la nota risultante.

Sarebbero 31 byte se -4e 4fossero accettabili come valori di input dell'indicatore chiave (quindi Ñi+_⁸?4ị¢può diventare Ñi+⁸ị¢) ma questo è stato chiarito come non consentito a meno che -4 sia falso e 4 sia vero, il che non è il caso di Jelly.

Come?

Costruisce una tastiera con fantasma B#e E#tasti, trova l'indice dell'input, compensa che 4nella direzione richiesta, si ricollega in una tastiera con quei tasti fantasma sostituiti dai risultati richiesti (il tasto sopra di loro):

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

Segno di spunta verde: Hmm, quindi nessuno ha ancora battuto questo punteggio - Sono abbastanza scioccato.
Jonathan Allan,

9

Befunge, 70 64 byte

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

Provalo online!

L'input dovrebbe essere nella forma C# Trebleo F Bass, sebbene la chiave possa essere semplicemente la prima lettera (ovvero To B), poiché il resto dell'input viene comunque ignorato.

Spiegazione

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

Come risultato di questa modifica del codice, la sequenza successiva di istruzioni prenderà una delle due forme seguenti:

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

A questo 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.

A questo punto lo stack contiene note,0o solo note(con uno zero implicito di seguito).

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

Prende ingresso nella sintassi rifinizione (note)(clef)dove clefè 0per bassi e 1per alti .

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

dimostrazione

Come?

Questo in realtà è leggermente meno divertente della mia versione precedente, ma la tabella di ricerca sottostante è ora F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fche consente di abbreviare la condizione # evitando il trucco del carattere NUL - che era un po 'border-line, suppongo.


Versione precedente 76 75 byte

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

dimostrazione

Come?

L'input (n, c) viene elaborato attraverso i seguenti passaggi:

  1. Valutiamo innanzitutto 4 * !!n[1] + c + ndove !!n[1]è vero (costretto a 1 ) se la nota contiene un # , e falso (costretto a 0 ) altrimenti. L'espressione 4 * !!n[1] + cproduce un valore numerico che viene aggiunto davanti alla stringa n .

  2. Passo implicito: gli zeri iniziali e i # finali sono ignorati da parseInt(). Ad esempio, "5G#"viene effettivamente analizzato come "5G".

  3. Convertiamo la nuova stringa in un valore decimale analizzandola come quantità base-21.

  4. Applichiamo il modulo 24.

  5. Applichiamo il modulo 17.

Di seguito è riportata la tabella di riepilogo per tutte le possibili coppie di input, insieme all'output previsto. Si noti che è necessario aggiungere un # all'output se il risultato finale è 0 , 2 , 3 o 5 . Da qui l'uso della maschera binaria 101101 ( 45 in decimale).

 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 byte

Funzione su cui stampare STDOUT. Trueconverte i bassi in alti e li Falseconverte in bassi.

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]

Provalo online!

Spiegazione:

  • La prima istruzione, N=ord(n[0])-63-4*c;calcola l'indice (da 0 a 7) della lettera della nuova nota, ignorando gli oggetti taglienti.
    • ord(N[0])-63-4*cottiene l'indice della lettera corrente e aggiunge o sottrae 2 in base al valore di c(variabile per cambiare la direzione di conversione)
  • La prossima affermazione M=-~N%3<1<len(n);calcola se questa variabile dovrà essere modificata o meno. Ad esempio, se la nuova nota è E, e la nota originale aveva una nitidezza, questa dovrà essere regolata su un F. La disuguaglianza incatenata funziona come segue:
    • -~N%3<1controlla se l'indice della nuova nota è nella sequenza 3n-1. Questo produrrà solo per Ee B, le due note che non hanno un sharp.
    • 1<len(n)controlla se la nota originale aveva un segno acuto (ciò renderebbe la lunghezza della stringa maggiore di 1). Ciò è necessario in quanto, se non vi era alcun segno di spunta, non è necessario regolare le nuove lettere della nota.
    • Questo imposta il valore di Ma Trueo False, che può essere usato nel calcolo come 1e 0rispettivamente, quindi per eseguire la regolazione dobbiamo solo aggiungere M a N e modulo di 7.
  • L'istruzione finale crea e produce il risultato finale.
    • chr((N+M)%7+65) aggiunge la regolazione, se necessario, quindi converte il valore da un indice a un carattere.
    • +n[1:2-M]aggiungerà un simbolo acuto se entrambi M=0(nessuna regolazione è stata effettuata) e anche il valore originale aveva un segno acuto.

1
Siamo spiacenti, solo 0 & 1, Truthey & Falsey o T&B
FantaC

@tfbninja grazie per il chiarimento
FlipTack

2

Java 8, 119 byte

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]

Spiegazione:

Provalo qui.

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
un'altra soluzione con 99 byte:n->b->((char)((n.charAt(0)-(b?0:4))%7+65)+n.substring(1)).replaceAll("B#","C").replaceAll("E#","F")
Nahuel Fouilleul

@NahuelFouilleul Ah nice! Stavo davvero pensando a qualcosa con un cast e un modulo potrebbe essere più breve. Ma poiché è un po 'troppo diverso dalla mia risposta attuale, sentiti libero di pubblicarlo come risposta separata. Hai il mio voto se lo fai. :)
Kevin Cruijssen il

0

R , 111 byte

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

Provalo online!

Ungolfed:

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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.