Konwertuj między kluczami muzycznymi

12

Przed wyjazdem nie musisz rozumieć dużej ilości zapisu muzycznego, aby wykonać to wyzwanie.

WYJAŚNIENIE

W standardowym zapisie nutowym podwójne strony otwierają się na całej stronie i służą jako punkty odniesienia do nut, informując, jaką nutę należy zagrać. Jeśli nie znasz jeszcze klucza wiolinowego i basowego, oto opis z Wikipedii:

Klucz wiolinowy to muzyczny symbol używany do oznaczania wysokości zapisanych nut. Umieszczony w jednym z wierszy na początku pięciolinii wskazuje nazwę i wysokość nut w tym wierszu. Ta linia służy jako punkt odniesienia, za pomocą którego można określić nazwy nut w dowolnej innej linii lub przestrzeni pięciolinii.

Nuty

Na powyższym obrazku górna połowa linii to klucz wiolinowy, oznaczony symbolem Potrójny klucz wiolinowy

Dolna połowa to klucz basowy oznaczony symbolem Bass Clef

Jak widać na klucz wiolinowy nuty na dolnej linii jest najbardziej E . (Nie liczę notatki poza kluczu liniami na to wyzwanie) Na kluczu basowym, najniższa linia jest G . Aby ukończyć to wyzwanie, musisz wykonać następujące czynności:

WYZWANIE

Biorąc pod uwagę dane wejściowe w jednej z następujących form (twój wybór), przekonwertuj je na przeciwny klucz. To, czy jest to klucz wiolinowy, czy basowy, może być wartością Truthey / Falsey w twoim języku (nie tylko dwiema wartościami), np.

F # T lub F # True lub F # Treble

ale nie

F # -1 lub F # 4

Spacje i wielkie litery są opcjonalne, Flats się nie pojawi, a końcowe białe znaki nie są dozwolone.

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#

Ostrzegamy, że nie jest to banalne wyzwanie polegające na stałej różnicy. Przyjrzyj się uważnie wejściom i wyjściom. Jeśli spojrzysz na pianino,

Fortepian

czarne klawisze to ostre, oznaczone przez #. Zauważ, że nie ma E # ani B #. Oznacza to, że jeśli otrzymasz klucz G # na kluczu basowym, zamiast zwracać E # , musisz zwrócić F.

To jest , więc wygrywa najmniejsza liczba bajtów.

FantaC
źródło
1
Czy musimy się martwić o mieszkania? Co powiesz na podwójne mieszkania / ostre narzędzia?
mypetlion
1
Nie twórz tagów dla tematów, które ich nie gwarantują.
Jonathan Allan
3
Czy końcowe białe znaki (zwracane C zamiast C) są w porządku?
Lynn,
2
Czy używanie 1i -1(lub nawet mówienie 4i -4) wprowadzania danych wskaźnika klucza jest dozwolone, czy byłoby to dopuszczalne tylko wtedy, gdy są to wartości prawdy / falseya w naszym języku?
Jonathan Allan,
1
To miłe i dobrze przedstawione wyzwanie, ale byłoby jeszcze lepiej IMO z nieco zrelaksowanymi formatami wejścia / wyjścia.
Arnauld,

Odpowiedzi:

5

Galaretka ,  35  34 bajtów

Mam wrażenie, że pewna arytmetyka może wygrać z tą metodą.

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

Wypróbuj online!

Pełny program z 1) wskaźnikiem klucza 0lub odpowiednio 1dla basów lub tonów wysokich i 2) nutą; i wydrukowanie powstałej notatki.

Byłoby 31 bajtów, gdyby -4i 4były akceptowalne jako wartości wejściowe wskaźnika klucza (wówczas Ñi+_⁸?4ị¢mogą się stać Ñi+⁸ị¢), ale zostało to wyjaśnione jako niedozwolone, chyba że -4 oznacza falsey, a 4 to prawda, co nie jest prawdą w przypadku Jelly.

W jaki sposób?

Buduje klawiaturę z fantomem B#i E#klawiszami, znajduje indeks danych wejściowych, kompensuje, że 4w wymaganym kierunku, indeksuje z powrotem w klawiaturę, zastępując te klawisze fantomów wymaganymi wynikami (klawisz nad nimi):

Ø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
źródło
Zielony czek: Hmm, więc nikt jeszcze nie pobił tego wyniku - jestem dość zszokowany.
Jonathan Allan,
9

Befunge, 70 64 bajtów

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

Wypróbuj online!

Dane wejściowe powinny mieć postać C# Treblelub F Bass, chociaż kluczem może być po prostu pierwsza litera (tj. TLub B), ponieważ reszta danych wejściowych jest ignorowana.

Wyjaśnienie

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

W wyniku tej modyfikacji kodu następna sekwencja instrukcji przyjmie jedną z dwóch postaci:

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

W tym momencie stos zawiera note,0,sharp,spacealbo 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.

W tym momencie stos zawiera note,0albo po prostu note(z domyślnym zerem poniżej).

+         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
źródło
3

Perl 5, 56 bajtów

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

Odczytuje nutę i klucz wiolinowy jako dwie linie ze STDIN i drukuje nową notatkę do STDOUT. Klucz jest 0przeznaczony dla tonów wysokich i 1basów.

faubi
źródło
1
można zapisać 11 bajtów przy użyciu -pflagi tio.run
Nahuel Fouilleul
3

JavaScript (ES6) 74 bajty

Trwa wejście w currying składni (note)(clef), gdzie clefjest 0na basie i 1na wysokich tonów .

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

Próbny

W jaki sposób?

To jest rzeczywiście nieco mniej zabawne niż moja poprzednia wersja, ale podstawowa tabela odnośników F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fpozwala teraz skrócić warunek # , unikając sztuczki znakowej NUL - która, jak sądzę, była nieco pogranicza.


Poprzednia wersja 76 75 bajtów

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

Próbny

W jaki sposób?

Dane wejściowe (n, c) są przetwarzane przez następujące kroki:

  1. Najpierw oceniamy, 4 * !!n[1] + c + ngdzie !!n[1]jest prawdziwe (wymuszone na 1 ), jeśli nuta zawiera # , a fałszywe (wymuszone na 0 ) w przeciwnym razie. Wyrażenie 4 * !!n[1] + cskutkuje wartością liczbową, która jest dodawana przed ciągiem n .

  2. Niejawny krok: wiodące zera i końcowe # są ignorowane przez parseInt(). Na przykład "5G#"jest faktycznie analizowany jako "5G".

  3. Konwertujemy nowy ciąg na wartość dziesiętną, analizując go jako liczbę podstawową 21.

  4. Stosujemy modulo 24.

  5. Stosujemy modulo 17.

Poniżej znajduje się tabela podsumowująca dla wszystkich możliwych par danych wejściowych wraz z oczekiwanym wynikiem. Zauważ, że do wyniku należy dodać #, jeśli końcowy wynik to 0 , 2 , 3 lub 5 . Stąd użycie maski binarnej 101101 ( 45 w systemie dziesiętnym).

 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
źródło
3

Python 2 , 77 bajtów

Funkcja, która drukuje do STDOUT. Truekonwertuje tony niskie na wysokie i Falsekonwertuje tony wysokie na niskie.

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]

Wypróbuj online!

Wyjaśnienie:

  • Pierwsze zdanie N=ord(n[0])-63-4*c;oblicza indeks (od 0 do 7) listu nowej nuty, nie uwzględniając ostrych krawędzi.
    • ord(N[0])-63-4*cpobiera indeks bieżącej litery i dodaje lub odejmuje 2 w zależności od wartości c(zmiennej do zmiany kierunku konwersji)
  • Następna instrukcja M=-~N%3<1<len(n);oblicza, czy ta zmienna będzie musiała zostać dostosowana. Na przykład, jeśli nowa nuta jest E, a oryginalna nuta była ostra, należy ją dostosować do F. Łańcuchowa nierówność działa w następujący sposób:
    • -~N%3<1sprawdza, czy indeks nowej nuty jest w sekwencji 3n-1. To da tylko prawdę dla Ei B, dwie nuty, które nie mają ostrego.
    • 1<len(n)sprawdza, czy oryginalna nuta była ostra (spowodowałoby to, że długość struny byłaby większa niż 1). Jest to konieczne, ponieważ jeśli nie było ostre, nie ma potrzeby dostosowywania nowych liter notatek.
    • To ustawia wartość Malbo, Truealbo False, które mogą być użyte w obliczeniach odpowiednio 1i 0, więc aby wykonać dopasowanie, potrzebujemy tylko dodać M do N i modulo o 7.
  • Ostateczne stwierdzenie tworzy i generuje wynik końcowy.
    • chr((N+M)%7+65) w razie potrzeby dodaje dopasowanie, a następnie konwertuje wartość z indeksu z powrotem na znak.
    • +n[1:2-M]doda ostry symbol, jeśli oba M=0(nie dokonano żadnej regulacji), a oryginalna wartość również była ostra.
FlipTack
źródło
1
Przepraszamy, tylko 0 i 1, Truthey & Falsey lub T&B
FantaC
@tfbninja dzięki za wyjaśnienie
FlipTack
2

Java 8, 119 bajtów

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]

Wyjaśnienie:

Wypróbuj tutaj.

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
źródło
1
inne rozwiązanie z 99 bajtami:n->b->((char)((n.charAt(0)-(b?0:4))%7+65)+n.substring(1)).replaceAll("B#","C").replaceAll("E#","F")
Nahuel Fouilleul
@NahuelFouilleul Ah fajnie! Rzeczywiście myślałem o czymś z characterem, a jakieś modulo może być krótsze. Ale ponieważ jest to trochę zbyt różne od mojej obecnej odpowiedzi, możesz opublikować ją jako osobną odpowiedź. Masz moją opinię, jeśli tak. :)
Kevin Cruijssen
0

R , 111 bajtów

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

Wypróbuj online!

Nie golfowany:

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
}
użytkownik2390246
źródło