Konversi antara Kunci musik

12

Sebelum Anda pergi, Anda tidak perlu memahami banyak notasi musik untuk melakukan tantangan ini.

PENJELASAN

Dalam musik lembar standar, double clefs melintasi halaman yang berfungsi sebagai titik referensi ke not, sehingga Anda tahu not apa yang harus dimainkan. Jika Anda belum terbiasa dengan treble dan bass clef, berikut adalah deskripsi dari Wikipedia:

Clef adalah simbol musik yang digunakan untuk menunjukkan nada not tertulis. Ditempatkan pada salah satu garis di awal paranada, itu menunjukkan nama dan nada catatan pada garis itu. Baris ini berfungsi sebagai titik referensi dimana nama catatan pada baris lain atau ruang paranada dapat ditentukan.

Lembaran musik

Pada gambar di atas, bagian atas dari garis adalah kunci Treble, dilambangkan dengan a Treble Clef

Setengah bagian bawah adalah kunci Bass, dilambangkan dengan a Bass Clef

Seperti yang Anda lihat di treble clef catatan di paling bawah garis adalah E . (Saya tidak menghitung catatan di luar garis clef untuk tantangan ini) Di clef bass, garis terendah adalah G . Untuk menyelesaikan tantangan ini, Anda harus melakukan hal berikut:

TANTANGAN

Diberikan input dalam salah satu bentuk berikut (pilihan Anda), mengubahnya menjadi kunci sebaliknya. Apakah itu Treble atau Bass clef dapat menjadi nilai Truthey / Falsey dalam bahasa Anda (bukan sembarang dua nilai), mis.

F # T atau F # True atau F # Treble

tapi tidak

F # -1 atau F # 4

Spasi dan kapitalisasi adalah opsional, Susun tidak akan muncul, dan trailing spasi tidak diizinkan.

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#

Diperingatkan, ini bukan tantangan perbedaan konstan sepele. Perhatikan baik-baik input dan output. Jika Anda melihat piano,

Piano

kunci hitam adalah benda tajam, dilambangkan dengan #. Perhatikan bahwa tidak ada E # atau B #. Ini berarti bahwa jika Anda diberikan G # pada kunci Bass, alih-alih mengembalikan E # , Anda harus mengembalikan F

Ini adalah , sehingga byte-count terkecil menang.

FantaC
sumber
1
Apakah kita harus khawatir tentang flat? Bagaimana dengan flat ganda / benda tajam?
mypetlion
1
Tolong jangan membuat tag untuk topik yang tidak menjamin mereka.
Jonathan Allan
3
Apakah trailing whitespace (mengembalikan C bukan C) oke?
Lynn
2
Apakah menggunakan 1dan -1(atau bahkan mengatakan, 4dan -4) untuk input indikator clef diperbolehkan atau apakah ini hanya dapat diterima jika nilai-nilai itu benar / salah dalam bahasa kita?
Jonathan Allan
1
Ini adalah tantangan yang bagus dan disajikan dengan baik, tetapi IMO akan lebih baik dengan format input / output yang sedikit lebih santai.
Arnauld

Jawaban:

5

Jelly ,  35  34 byte

Saya merasa beberapa aritmatika dapat memenangkan metode ini.

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

Cobalah online!

Sebuah program penuh mengambil 1) indikator clef 0atau 1untuk Bass atau Treble masing-masing dan 2) catatan; dan mencetak catatan yang dihasilkan.

Akan menjadi 31 byte jika -4dan 4dapat diterima sebagai nilai input indikator kunci (kemudian Ñi+_⁸?4ị¢dapat menjadi Ñi+⁸ị¢) tetapi ini telah diklarifikasi sebagai tidak diizinkan kecuali -4 adalah palsu dan 4 benar, yang tidak berlaku untuk Jelly.

Bagaimana?

Buat keyboard dengan phantom B#dan E#kunci, temukan indeks input, offset yang dengan 4arah yang diperlukan, indeks kembali ke keyboard dengan kunci phantom digantikan oleh hasil yang diperlukan (tombol di atas mereka):

Ø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
sumber
Cek hijau: Hmm, jadi belum ada yang mengalahkan skor ini - saya cukup terkejut.
Jonathan Allan
9

Befunge, 70 64 byte

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

Cobalah online!

Input harus dalam bentuk C# Trebleatau F Bass, meskipun kunci dapat dengan mudah menjadi huruf pertama (yaitu Tatau B), karena sisa input diabaikan.

Penjelasan

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

Sebagai hasil dari modifikasi kode ini, urutan instruksi selanjutnya akan mengambil satu dari dua bentuk:

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

Pada titik ini tumpukan berisi note,0,sharp,spaceatau 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.

Pada titik ini tumpukan berisi note,0atau hanya note(dengan nol implisit di bawah).

+         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
sumber
3

Perl 5, 56 byte

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

Membaca note dan clef sebagai dua baris dari STDIN dan mencetak note baru ke STDOUT. Kunci 0untuk treble dan 1untuk bass.

faubi
sumber
1
dapat menghemat 11 byte menggunakan -pflag tio.run/##K0gtyjH9/79YX08/OaNIwcxUW0PXRMvGTju/KEVFTVPVXD/…
Nahuel Fouilleul
3

JavaScript (ES6) 74 byte

Mengambil input dalam sintaks currying (note)(clef)mana clefadalah 0untuk bass dan 1untuk treble .

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

Demo

Bagaimana?

Ini sebenarnya sedikit kurang menyenangkan daripada versi saya sebelumnya, tetapi tabel pencarian yang mendasarinya sekarang F#,C#,(unused),D#,A#,F,C,G,D,A,E,B,Fmemungkinkan untuk memperpendek kondisi # sambil menghindari trik karakter NUL - yang agak garis batas, saya kira.


Versi sebelumnya 76 75 byte

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

Demo

Bagaimana?

Input (n, c) diproses melalui langkah-langkah berikut:

  1. Kami pertama mengevaluasi 4 * !!n[1] + c + nmana !!n[1]yang benar (dipaksa untuk 1 ) jika catatan berisi # , dan palsu (dipaksa untuk 0 ) sebaliknya. Ekspresi 4 * !!n[1] + cmenghasilkan nilai numerik yang ditambahkan di depan string n .

  2. Langkah tersirat: angka nol di depan dan # jejak diabaikan oleh parseInt(). Misalnya, "5G#"sebenarnya diurai sebagai "5G".

  3. Kami mengonversi string baru ke nilai desimal dengan menguraikannya sebagai kuantitas basis-21.

  4. Kami menerapkan modulo 24.

  5. Kami menerapkan modulo 17.

Di bawah ini adalah tabel ringkasan untuk semua pasangan input yang memungkinkan, bersama dengan output yang diharapkan. Perhatikan bahwa # harus ditambahkan ke output jika hasil akhirnya adalah 0 , 2 , 3 atau 5 . Oleh karena itu penggunaan topeng biner 101101 ( 45 dalam desimal).

 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
sumber
3

Python 2 , 77 byte

Fungsi yang mencetak ke STDOUT. Truemengkonversi bass ke treble, dan Falsemengubah treble ke bass.

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]

Cobalah online!

Penjelasan:

  • Pernyataan pertama N=ord(n[0])-63-4*c;,, menghitung indeks (0 hingga 7) dari surat catatan baru, mengabaikan benda tajam.
    • ord(N[0])-63-4*cmendapatkan indeks huruf saat ini, dan menambah atau mengurangi 2 tergantung pada nilai c(variabel untuk beralih arah konversi)
  • Pernyataan berikutnya, M=-~N%3<1<len(n);menghitung apakah variabel ini perlu disesuaikan atau tidak. Misalnya, jika catatan baru E, dan catatan asli memiliki nada tajam, ini harus disesuaikan dengan F. Ketidaksetaraan dirantai bekerja sebagai berikut:
    • -~N%3<1memeriksa apakah indeks not baru dalam urutan 3n-1. Ini hanya akan menghasilkan true untuk Edan B, dua not yang tidak memiliki tajam.
    • 1<len(n)memeriksa apakah not asli memiliki tajam (ini akan membuat panjang string lebih besar dari 1). Ini perlu karena, jika tidak ada yang tajam, tidak perlu menyesuaikan surat-surat catatan baru.
    • Ini menetapkan nilai Muntuk salah satu Trueatau False, yang dapat digunakan dalam perhitungan sebagai 1dan 0masing - masing, sehingga untuk melakukan penyesuaian kita hanya perlu menambahkan M ke N dan modulo dengan 7.
  • Pernyataan akhir menciptakan dan menampilkan hasil akhir.
    • chr((N+M)%7+65) menambahkan penyesuaian jika perlu, lalu mengonversi nilai dari indeks kembali ke karakter.
    • +n[1:2-M]akan menambahkan simbol yang tajam jika keduanya M=0(tidak ada penyesuaian dibuat) dan nilai aslinya juga memiliki yang tajam.
FlipTack
sumber
1
Maaf, hanya 0 & 1, Truthey & Falsey, atau T&B
FantaC
@tfbninja terima kasih atas klarifikasi
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]

Penjelasan:

Coba di sini.

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
sumber
1
solusi lain dengan 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 bagus! Saya memang sedang memikirkan sesuatu dengan karakter dan beberapa modulo mungkin lebih pendek. Tetapi karena ini agak terlalu berbeda dari jawaban saya saat ini, jangan ragu untuk mempostingnya sebagai jawaban terpisah. Anda mendapat dukungan saya jika melakukannya. :)
Kevin Cruijssen
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])]))

Cobalah online!

Tidak Disatukan:

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
}
pengguna2390246
sumber