Dikotomi Mayor-Minor

15

Diberikan daftar akord label mereka sebagai 'Mayor' atau 'Kecil'.

Memasukkan

Input akan berupa daftar akord, satu per baris, terdiri dari 3 not yang dipisahkan oleh spasi. Setiap note akan terdiri dari nama note dalam huruf besar ( A- G) dan opsional kebetulan ( #atau b). Akord mungkin ada dalam inversi apa pun (mis. Not mungkin dalam urutan apa pun).

Keluaran

Jika chordnya mayor, keluaran 'Mayor'. Jika akornya minor, keluaran 'Minor'. Jika akornya tidak besar atau kecil, keluaran baris kosong.

Contoh

Memasukkan

C E G
F Ab C
C Eb Gb
E G B
Db F Ab
Bb G D
D A Gb

Keluaran

Major
Minor

Minor
Major
Minor
Major

Skrip uji

Seperti pada beberapa pertanyaan saya di masa lalu, saya sekali lagi membantai beberapa skrip uji yang awalnya dibuat oleh Joey dan Ventero untuk memberikan beberapa kasus uji untuk pertanyaan ini:

Pemakaian: ./test [your program and its arguments]

Hadiah

Setiap entri yang saya dapat verifikasi yang memenuhi spesifikasi, lulus tes dan jelas telah mencoba golf akan menerima upvote dari saya (jadi tolong berikan instruksi penggunaan dengan jawaban Anda). Solusi terpendek pada akhir 13/10/2012 akan diterima sebagai pemenang.

Sedikit teori

Bagi Anda yang tidak memiliki pengetahuan teori musikal, inilah informasi yang cukup bagi Anda untuk dapat bersaing.

Akord mayor atau minor terdiri dari tiga not yang dipisahkan oleh pola semitone tertentu. Jika kita menganggap root (nada bawah) dari akor menjadi 0, maka akor mayor adalah pola 0-4-7 dan akor minor adalah pola 0-3-7. Hal-hal dibuat lebih canggung oleh kenyataan bahwa beberapa not adalah nada semi terpisah dan beberapa nada terpisah. Sebaran semiton dari Ab- G#adalah sebagai berikut:

G#/Ab A A#/Bb B/Cb B#/C C#/Db D D#/Eb E/Fb E#/F F#/Gb G G#/Ab
  0   1   2    3     4    5   6   7    8     9    10  11  12

G#/Abberarti bahwa itu G#adalah catatan yang sama dengan Ab. Dari sini kita dapat melihat bahwa akord Ab C Ebadalah akord mayor, dan itu Ab Cb Ebminor.

Untuk memperumit masalah lebih lanjut, chord Eb Cb Abdianggap sama dengan Ab Cb Eb, Cb Eb Abdan Cb Ab Ebdan sebagainya. Setiap variasi ini masih merupakan kunci minor.

Gareth
sumber
2
Saya pikir bash tester Anda membutuhkan input dan jawaban yang diharapkan sudah diganti.
flodel
@ model Ya, Anda benar. Maaf tentang itu, saya sudah memperbaikinya sekarang. Saya perlu memeriksa bahwa skrip tes Powershell tidak memiliki masalah yang sama juga.
Gareth

Jawaban:

3

GolfScript, 83 karakter

n%{' '%{1\{'A#BC D EF G'?+}/.}%$(+2/{~- 12%}%.(+.(+]$0=.$]10,7>?'MMaijnoorr

'>2%}%

Ini adalah solusi cepat pertama; Saya yakin ini bisa bermain golf lebih lanjut. Lulus bash test suite, setelah memperbaiki bug yang ditunjukkan oleh flodel di komentar.

Sunting 1: Disimpan 5 karakter dengan cara yang lebih pendek untuk mengenali pola akor mayor dan minor yang dikanonikalisasi.

Sunting 2: Disimpan 2 karakter lagi dengan pengkodean keluaran yang lebih kompak yang terinspirasi oleh solusi grc. (Terima kasih!) Sebagai efek samping, kode sekarang mencetak baris kosong tambahan setelah output, tetapi test harness tampaknya menerimanya, jadi saya rasa tidak apa-apa. :)

Begini cara kerjanya:

  • Lingkaran luar n%{ }%n*hanya membagi input menjadi garis, menjalankan kode di dalam kurung untuk setiap baris dan bergabung dengan hasilnya dengan baris baru.

  • ' '%membagi setiap baris menjadi array catatan. Untuk masing-masing catatan itu, 1\{'A#BC D EF G'?+}/kemudian mengonversi catatan itu menjadi angka semitone dengan mencari setiap karakter dalam string 'A#BC D EF G'dan menambahkan posisi (yang akan -1 untuk setiap karakter yang tidak ditemukan dalam string, terutama termasuk b). (Saya yakin saya pernah melihat trik ini digunakan sebelumnya.) Akhirnya, .duplikat setiap angka, sehingga, pada akhir loop, misalnya input F Ab Ctelah diubah menjadi [9 9 0 0 4 4].

  • Kami kemudian mengurutkan catatan dengan $, memindahkan catatan pertama ke akhir dengan (+, dan membagi array menjadi berpasangan 2/, sehingga sekarang terlihat seperti misalnya [[9 0] [0 4] [4 9]]. Kemudian {~- 12%}%memetakan setiap pasangan catatan ke modulo 12 perbedaannya, mengubah array contoh kita menjadi [9 8 7].

  • Selanjutnya, .(+buat salinan array dan putar elemen-elemennya ke kiri dengan satu posisi. Kami melakukan ini dua kali dan mengumpulkan salinan ke dalam array ], sehingga contoh kita sekarang terlihat seperti [[9 8 7] [8 7 9] [7 9 8]].

  • Kami kemudian mengurutkan array array ini dengan $dan mengambil elemen pertama - dalam hal ini [7 9 8]- dengan 0=. Kami kemudian membuat salinan array ini ( .), mengurutkannya ( $), mengumpulkan array yang tidak disortir dan yang tidak disortir ke dalam array array yang lain ( ]), dan mencari kemunculan array yang pertama [7 8 9](yang ditulis 10,7>untuk menyimpan dua karakter ) di dalamnya.

  • Ini memberi kita baik 0(jika array yang tidak disortir adalah [7 8 9], dan dengan demikian chord adalah mayor), 1(jika array yang tidak disortir adalah permutasi [7 8 9], yang, mengingat bahwa elemen pertamanya harus terkecil, hanya bisa [7 9 8], membuat chord minor) atau -1(jika bahkan array yang diurutkan tidak sama [7 8 9]).

  • Angka ini kemudian digunakan sebagai indeks awal ke dalam string "MMaijnoorr\n\n"(di mana \ns diberikan sebagai umpan baris aktual dalam kode), dari mana kita mengambil karakter itu dan setiap detik berikutnya sebagai output. Jika indeksnya -1, kita mulai dari karakter terakhir dari string, yang hanya berupa umpan baris.

Ilmari Karonen
sumber
Penjelasan yang bagus. Saya mengalami kesulitan yang sama dengan yang selalu saya alami dengan GolfScript - saya dapat meminta satu baris pada satu waktu untuk mengujinya, echo "G# B# Eb" | ruby golfscript.rb ilmari.gstetapi bagaimana cara menjalankan skrip uji di atasnya? Saya mencoba ./test ruby golfscript.rb ilmari.gstetapi tidak memilikinya. (Saya sudah memberi Anda +1 karena jelas berhasil, tapi saya hanya ingin tahu)
Gareth
1
@ Gareth: Sepertinya itu bug dalam skrip uji bash - tidak menangani beberapa argumen dengan benar. Untuk memperbaikinya, ganti args="$@"dengan args=("$@")dan got=$("$cmd" "$args")dengan got=$("$cmd" "${args[@]}"). (Atau hanya membuat golfscript.rbexecutable dan menjalankannya sebagai ./test ./golfscript.rb chords.gs.)
Ilmari Karonen
4

Python, 160

f='A#BC D EF G3453543'.find
try:
 while 1:x,y,z=sorted(map(lambda x:f(x[0])+f(x[1:])+1,raw_input().split()));print'MMianjoorrr'[f(`y-x`+`z-y`)/14:-1:2]
except:0
grc
sumber