Latar Belakang
Dalam musik Barat, setiap not tunggal memiliki nama yang ditetapkan. Dalam setiap oktaf, ada dua belas nada unik dalam urutan berikut: "CC # / Db DD # / Eb EFF # / Gb GG # / Ab AA # / Bb B C", di mana C terakhir adalah satu oktaf di atas yang pertama.
Untuk mengetahui perbedaan antara not oktaf yang berbeda, angka (untuk tantangan ini terbatas pada satu digit) ditambahkan ke akhir nama not. Jadi, C5 adalah not yang satu oktaf di atas C4. Bb6 di atas B5.
Fakta penting adalah bahwa B5 dan C6 adalah not yang bersebelahan, dan bahwa C0 dan B9 adalah not terendah dan tertinggi.
Di antara dua not, ada jarak yang merupakan jumlah semitone di antara mereka. Bb4 adalah satu semiton di bawah B4, yang merupakan satu semitone di bawah C5. Ada dua belas semiton dalam satu oktaf, jadi Bb4 adalah jarak 12 dari A # 3 karena itu adalah satu oktaf di atasnya (perhatikan bagaimana satu not dapat memiliki hingga dua nama).
Tantangan
Tantangan Anda adalah menulis program sesingkat mungkin yang dapat mengambil daftar catatan musik dari STDIN dan mencetak daftar perubahan interval ke STDOUT.
Input akan berupa daftar catatan musik yang dipisahkan ruang. Setiap catatan akan terdiri dari huruf besar AG, tanda b atau # opsional, dan satu digit angka. Anda tidak harus berurusan dengan E # / Fb atau B # / Cb. Input contoh:
C4 D4 E4 F4 G4 A4 B4 C5 C4
Output akan berupa daftar bilangan bulat yang dipisahkan oleh spasi yang mewakili jarak antara setiap not berurutan, selalu diawali dengan + atau - untuk menunjukkan apakah not naik atau turun relatif terhadap yang sebelumnya. Akan selalu ada satu nomor lebih sedikit yang dihasilkan dari catatan yang dimasukkan. Contoh output untuk input di atas:
+2 +2 +1 +2 +2 +2 +1 -12
Beberapa contoh input lainnya:
E5 D#5 E5 B4 E5 F#5 E5 B4
C0 B0 Bb1 A2 G#3 G4 F#5 F6
G4 Ab4 Gb4 A4 F4 A#4
Dan output yang sesuai:
-1 +1 -5 +5 +2 -2 -5
+11 +11 +11 +11 +11 +11 +11
+1 -2 +3 -4 +5
Aturan dan Batasan
Pemenang ditentukan oleh jumlah karakter dalam kode sumber
Program Anda harus terdiri dari hanya karakter ASCII yang dapat dicetak
Anda tidak diizinkan menggunakan fungsi bawaan apa pun yang terkait dengan musik atau suara
Selain itu, aturan golf kode standar berlaku
sumber
+0
atau-0
atau0
dua catatan identik?Jawaban:
GolfScript, 61
sumber
Haskell, 161 karakter
sumber
Perl, 103
sumber
C, 123 karakter
Berdasarkan solusi leftaroundabout, dengan beberapa perbaikan.
Beberapa trik yang menurut saya layak disebutkan:
1.
argv[0]
(di sini disebutb
) adalah pointer ke nama program, tetapi digunakan di sini sebagai buffer awal. Kami hanya membutuhkan 4 byte (mis.C#2\0
), Jadi kami sudah cukup.2.
c
adalah jumlah argumen, jadi itu dimulai sebagai 1 (ketika dijalankan tanpa argumen). Kami menggunakannya untuk mencegah pencetakan pada putaran pertama.Kemungkinan masalah -
c+=b[..c+=..]
agak aneh. Saya tidak berpikir itu perilaku yang tidak terdefinisi, karena?:
merupakan titik urutan, tapi mungkin saya salah.sumber
c = c + b[..c+=..]
, maka itu perilaku yang jelas tidak terdefinisi. Terlepas dari urutan dalam[..]
, Anda tidak tahu apakah bagian luarc
diambil sebelum, selama, atau setelahb[..]
.REG=c;REG+=b[..c+=..];c=REG
. Namun, saya akan terkejut melihat sesuatu seperti ini dalam praktek. Tapi tetap saja UB.scanf
tanpa prototipe, dan tidak apa-apa. Hanya baik untuk mengetahui apa yang legal dan tidak legal dalam kehidupan nyata :)C,
241229183sumber
printf("%+d ",c-d)
.F(*b-65)
alih-alihc-=65;
,b[1]<36&&++c||b[1]>97&&c--?2:1
->b[1]&16?1:(c+=b[1]%2*2-1,2)
, penyalahgunaanmain(e,b,c,d)char*b{
argumen oleh: (Gunakan penunjuk argumen pertama sebagai penyangga kantor).c=F(*b)%12
bisa diganti denganc=-~*b*1.6;c%=12
. Mengapa?sin
di aslinyaF
bisa diganti dengan 9.6.c*1.6+9.6
adalah(c+6)*1.6
,c-=65
dan(c+6)
menjadic-59
, dan kemudianc+1
(60 * 96% 12 == 0).Faktor, 303 karakter
Dengan komentar,
Untuk skrip ini, "daftar yang dipisahkan ruang" dapat memiliki 1 atau lebih spasi di antara elemen, dan 0 atau lebih spasi di awal atau akhir. Skrip ini memang mencetak ruang ekstra di akhir output, tetapi juga menerima ruang tambahan (atau baris baru) di akhir input.
Jika saya akan mengadopsi definisi yang lebih ketat, di mana "daftar yang dipisahkan oleh ruang" memiliki tepat 1 ruang antara elemen, dan 0 ruang di awal atau akhir, maka saya dapat mempersingkat
contents R/ [#-b]+/ all-matching-slices
menjadicontents " " split
(menggunakansplitting
, bukanregexp
). Namun, saya perlu menambahkan lebih banyak kode untuk mencegah ruang ekstra di akhir output.Jika saya menggunakan kata yang sudah tidak digunakan lagi
dupd
, saya dapat menyingkatover [ - "%+d " printf ] dip
menjadidupd - "%+d " printf
, menyimpan 8 karakter. Saya tidak menggunakan kata-kata usang karena mereka "dimaksudkan untuk segera dihapus."sumber