Apakah ini Skala Besar (atau setara)?

16

Bak pasir

Skala utama (atau skala Ionia) adalah salah satu skala musik yang paling umum digunakan, terutama dalam musik Barat. Ini adalah salah satu skala diatonis. Seperti banyak skala musik, itu terdiri dari tujuh not: yang kedelapan duplikat pertama di dua kali frekuensi sehingga disebut oktaf lebih tinggi dari not yang sama.

Tujuh not musik adalah:

C, D, E, F, G, A, B , C (diulang untuk tujuan contoh)

Skala utama adalah skala diatonis. Ambil suksesi catatan sebelumnya sebagai skala utama (Sebenarnya, Ini adalah skala C Mayor) . Urutan interval antara not skala besar adalah:

utuh, utuh, setengah, utuh, utuh, utuh, setengah

di mana "keseluruhan" adalah nada keseluruhan (kurva merah berbentuk u pada gambar), dan "setengah" berarti semitone (garis putus-putus merah pada gambar).

masukkan deskripsi gambar di sini

Dalam hal ini, dari C ke D ada nada keseluruhan , dari D ke E ada nada keseluruhan , dari E ke F ada setengah nada, dll ...

Kami memiliki 2 komponen yang memengaruhi jarak nada antara catatan. Ini adalah simbol Sharp (♯) dan simbol datar (♭).

Simbol Tajam (♯) menambahkan setengah nada pada catatan. Contoh. Dari C ke D kami sebutkan bahwa ada nada keseluruhan, jika kami menggunakan C♯ alih-alih C maka dari C♯ ke D ada setengah nada.

Simbol Flat (♭) melakukan kebalikan dari simbol Sharp, mengurangi setengah nada dari catatan. Contoh: Dari D ke E kami sebutkan bahwa ada nada keseluruhan, jika kami menggunakan Db sebagai gantinya maka dari Db ke E ada nada setengah.

Secara default, dari Note to Note ada seluruh nada kecuali untuk E to Fdan B to Cdi mana hanya setengah nada ada.

Catatan dalam beberapa kasus menggunakan pitch peningkatanarmonik dapat membuat setara dengan Skala Utama. Contoh dari ini adalah di C#, D#, E#, F#, G#, A#, B#, C#mana E#dan B#enharmonic tetapi skalanya mengikuti urutan Skala Utama.


Tantangan

Diberikan skala, hasilkan nilai kebenaran jika itu Skala Besar atau setara, jika tidak, hasilkan nilai falsey.

Aturan

  • Metode I / O standar diizinkan
  • Aturan standar berlaku
  • Anda tidak perlu mempertimbangkan not ke-8. Asumsikan input hanya akan terdiri dari 7 catatan
  • Asumsikan double flat ((), double sharp (♯♯) atau tanda natural (♮) tidak ada

Uji kasus

C, D, E, F, G, A, B                 => true
C#, D#, E#, F#, G#, A#, B#          => true
Db, Eb, F, Gb, Ab, Bb, C            => true
D, E, Gb, G, A, Cb, C#              => true
Eb, E#, G, G#, Bb, B#, D            => true
-----------------------------------------------
C, D#, E, F, G, A, B                => false
Db, Eb, F, Gb, Ab, B, C             => false
G#, E, F, A, B, D#, C               => false 
C#, C#, E#, F#, G#, A#, B#          => false
Eb, E#, Gb, G#, Bb, B#, D           => false
Luis felipe De jesus Munoz
sumber
@Abigail Pada dasarnya ya. Mereka memiliki nada yang sama meskipun mereka berbeda catatan.
Luis felipe De jesus Munoz
1
dan Cx (atau C ##) = D
SaggingRufus
1
Btw, skala Pentatonis tidak memiliki satu dari setiap huruf: v
Luis felipe De jesus Munoz
1
@Neil Timbangan kromatik tidak memiliki huruf unik dan saya yakin ada jenis skala yang tidak mengikuti urutan naik
Luis felipe De jesus Munoz
1
Saya harus menghapus ini karena @Neil menurunkannya terima kasih banyak
David Conrad

Jawaban:

11

Perl 6 , 76 65 63 59 byte

-4 byte terima kasih kepada Phil H

{221222==[~] (.skip Z-$_)X%12}o*>>.&{13*.ord+>3+?/\#/-?/b/}

Cobalah online!

Penjelasan

*>>.&{ ... }  # Map notes to integers
  13*.ord     # 13 * ASCII code:  A=845 B=858 C=871 D=884 E=897 F=910 G=923
  +>3         # Right shift by 3: A=105 B=107 C=108 D=110 E=112 F=113 G=115
              # Subtracting 105 would yield A=0 B=2 C=3 D=5 E=7 F=8 G=10
              # but isn't necessary because we only need differences
  +?/\#/      # Add 1 for '#'
  -?/b/       # Subtract 1 for 'b'

{                           }o  # Compose with block
            (.skip Z-$_)        # Pairwise difference
                        X%12    # modulo 12
         [~]  # Join
 221222==     # Equals 221222
nwellnhof
sumber
Jika Anda akan melakukan perbedaan berpasangan dan modulo 12, Anda tidak perlu mengurangi 105; itu hanya offset. -4 karakter: tio.run/…
Phil H
@ Philip Ya, tentu saja. Terima kasih!
nwellnhof
Itu cara yang sangat pintar untuk memetakan catatan ke nilai relatifnya, +1 dari saya!
Sok
10

Node.js v10.9.0 , 78 76 71 69 byte

a=>!a.some(n=>(a-(a=~([x,y]=Buffer(n),x/.6)-~y%61)+48)%12-2+!i--,i=3)

Cobalah online!

Bagaimana?

n[118,71]

[x, y] = Buffer(n) // split n into two ASCII codes x and y
~(x / .6)          // base value, using the ASCII code of the 1st character
- ~y % 61          // +36 if the 2nd character is a '#' (ASCII code 35)
                   // +38 if the 2nd character is a 'b' (ASCII code 98)
                   // +1  if the 2nd character is undefined

Pemberian yang mana:

  n   | x  | x / 0.6 | ~(x / 0.6) | -~y % 61 | sum
------+----+---------+------------+----------+------
 "Ab" | 65 | 108.333 |    -109    |    38    |  -71
 "A"  | 65 | 108.333 |    -109    |     1    | -108
 "A#" | 65 | 108.333 |    -109    |    36    |  -73
 "Bb" | 66 | 110.000 |    -111    |    38    |  -73
 "B"  | 66 | 110.000 |    -111    |     1    | -110
 "B#" | 66 | 110.000 |    -111    |    36    |  -75
 "Cb" | 67 | 111.667 |    -112    |    38    |  -74
 "C"  | 67 | 111.667 |    -112    |     1    | -111
 "C#" | 67 | 111.667 |    -112    |    36    |  -76
 "Db" | 68 | 113.333 |    -114    |    38    |  -76
 "D"  | 68 | 113.333 |    -114    |     1    | -113
 "D#" | 68 | 113.333 |    -114    |    36    |  -78
 "Eb" | 69 | 115.000 |    -116    |    38    |  -78
 "E"  | 69 | 115.000 |    -116    |     1    | -115
 "E#" | 69 | 115.000 |    -116    |    36    |  -80
 "Fb" | 70 | 116.667 |    -117    |    38    |  -79
 "F"  | 70 | 116.667 |    -117    |     1    | -116
 "F#" | 70 | 116.667 |    -117    |    36    |  -81
 "Gb" | 71 | 118.333 |    -119    |    38    |  -81
 "G"  | 71 | 118.333 |    -119    |     1    | -118
 "G#" | 71 | 118.333 |    -119    |    36    |  -83

12 antara nilai-nilai ini.

474×12=48 sebelum menerapkan modulo untuk memastikan bahwa kami mendapatkan hasil yang positif.

12'#'36mod12=0'b'38mod12=2 semiton.

aNaN .

[NaN,2,2,1,2,2,2] .

i12

Arnauld
sumber
Pendekatan hebat, jauh lebih menarik daripada jawaban saya
Skidsdev
4

JavaScript (Node.js) , 150 131 125 byte

l=>(l=l.map(x=>'C0D0EF0G0A0B'.search(x[0])+(x[1]=='#'|-(x[1]=='b')))).slice(1).map((n,i)=>(b=n-l[i])<0?2:b)+""=='2,2,1,2,2,2'

Cobalah online!

-19 byte berkat Luis felipe
-6 byte terima kasih kepada Shaggy

Tidak Terkumpul:

function isMajor(l) {
    // Get tone index of each entry
    let array = l.map(function (x) {
        // Use this to get indices of each note, using 0s as spacers for sharp keys
        let tones = 'C0D0EF0G0A0B';
        // Get the index of the letter component. EG D = 2, F = 5
        let tone = tones.search(x[0]);
        // Add 1 semitone if note is sharp
        // Use bool to number coercion to make this shorter
        tone += x[1] == '#' | -(x[1]=='b');
    });
    // Calculate deltas
    let deltas = array.slice(1).map(function (n,i) {
        // If delta is negative, replace it with 2
        // This accounts for octaves
        if (n - array[i] < 0) return 2;
        // Otherwise return the delta
        return n - array[i];
    });
    // Pseudo array-comparison
    return deltas+"" == '2,2,1,2,2,2';
}
Skidsdev
sumber
1
[...'C0D0EF0G0A0B']bukannya 'C0D0EF0G0A0B'.split('')dan +""bukannya .toString()menyimpan beberapa byte
Luis felipe De jesus Munoz
x[1]=='#'|-(x[1]=='b')alih-alih x[1]=='#'?1:(x[1]=='b'?-1:0)menyimpan beberapa byte juga
Luis felipe De jesus Munoz
@LuisfelipeDejesusMunoz Oh bagus terima kasih! Saya tidak percaya saya lupa tentang ekspansi array dan menambahkan string kosong
Skidsdev
"Jika delta negatif, ganti dengan 2" terdengar salah. Saya pikir Anda perlu mengambil modulo perbedaan 12.
nwellnhof
@nwellnhof Dalam pengujian saya, semua skala utama memiliki delta yang benar untuk memulai, atau, jika mereka membentang satu oktaf, memiliki satu delta di -10 daripada 2. Mengganti delta negatif memperbaikinya. Saya tidak berpikir -10 % 12 == 2. Meskipun dipikir-pikir ini mungkin gagal dalam beberapa kasus ...
Skidsdev
3

Dart , 198 197 196 189 byte

f(l){var i=0,j='',k,n=l.map((m){k=m.runes.first*2-130;k-=k>3?k>9?2:1:0;return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;}).toList();for(;++i<7;j+='${(n[i]-n[i-1])%12}');return'221222'==j;}

Cobalah online!

Port longgar dari jawaban Perl 6 yang lama /codegolf//a/175522/64722

f(l){
  var i=0,j='',k,
  n=l.map((m){
    k=m.runes.first*2-130;
    k-=k>3?k>9?2:1:0;
    return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;
  }).toList();
  for(;++i<7;j+='${(n[i]-n[i-1])%12}');
  return'221222'==j;
}
  • -1 byte dengan menggunakan operator ternary untuk # / b
  • -1 byte dengan menggunakan ifs alih-alih terner untuk pergeseran skala
  • -7 byte terima kasih kepada @Kevin Cruijssen

Versi lama :

Dart , 210 byte

f(l){var i=0,k=0,n={'C':0,'D':2,'E':4,'F':5,'G':7,'A':9,'B':11,'b':-1,'#':1},j='',y=[0,0];for(;++i<7;j+='${(y[0]-y[1])%12}')for(k=0;k<2;k++)y[k]=n[l[i-k][0]]+(l[i-k].length>1?n[l[i-k][1]]:0);return'221222'==j;}

Cobalah online!

Tidak Terkumpul:

f(l){
  var i=0,k=0,n={'C':0,'D':2,'E':4,'F':5,'G':7,'A':9,'B':11,'b':-1,'#':1},j='',y=[0,0];
  for(;++i<7;j+='${(y[0]-y[1])%12}')
    for(k=0;k<2;k++)
      y[k]=n[l[i-k][0]]+(l[i-k].length>1?n[l[i-k][1]]:0);

  return'221222'==j;
}

Seluruh langkah adalah 2, seperempat adalah 1. Mod 12 jika Anda melompat ke oktaf lebih tinggi. Iterasi semua not dan hitung perbedaan antara not ke-1 dan not ke-1. Menggabungkan hasilnya dan harus mengharapkan 221222 (2 keseluruhan, 1 setengah, 3 keseluruhan).

  • -2 byte dengan tidak menetapkan 0 ke k
  • -4 byte dengan menggunakan j sebagai String dan bukan Daftar
  • -6 byte terima kasih kepada @Kevin Cruijssen dengan menghapus kekacauan yang tidak perlu dalam loop
Elcan
sumber
Saya tidak tahu Dart, tetapi bagian-bagiannya mirip dengan Java. Oleh karena itu: mengubah i=1ke i=0dapat mengurangi byte dengan mengubah for(;i<7;i++)ke for(;++i<7;). Selain itu, kurung {}dapat dihapus sekitar loop itu, dengan menempatkan j+=...dalam bagian ketiga dari loop: for(;++i<7;j+='${(y[0]-y[1])%12}'). Dan satu hal lagi yang berubah return j=='221222';untuk return'221222'==j;menyingkirkan ruang. -6 ( 210 byte ) setelah modifikasi ini.
Kevin Cruijssen
Terima kasih, tidak tahu tentang trik-trik untuk loop
Elcan
Np. Dalam versi 196-byte baru Anda, Anda juga bisa mengubahnya menjadi 189 byte dengan mengubah if(k>9)k--;if(k>3)k--;ke k-=k>3?k>9?2:1:0;dan k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;ke return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen
Sial, sepertinya masih banyak yang harus kupelajari, terima kasih!
Elcan
Yah, saya sudah bermain golf selama 2,5 tahun sekarang, dan bahkan saya mendapatkan tips tentang golf setiap saat. :) Cukup mudah untuk melewatkan sesuatu sendiri pada awalnya, dan seiring waktu Anda memikirkan cara-cara berbeda untuk bermain golf. :) Tips untuk bermain golf di <semua bahasa> mungkin menarik untuk dibaca jika Anda belum. Dan beberapa Tips untuk bermain golf di Jawa mungkin juga berlaku di Dart, karena golf yang saya lakukan dalam jawaban Anda didasarkan pada pengetahuan Java saya, karena ini adalah pertama kalinya saya melihat Dart. ;)
Kevin Cruijssen
2

C (gcc) , -DA=a[i]+ 183 = 191 byte

f(int*a){char s[9],b[9],h=0,i=0,j=0,d;for(;A;A==35?b[i-h++-1]++:A^98?(b[i-h]=A*13>>3):b[i-h++-1]--,i++);for(;j<7;d=(b[j]-b[j-1])%12,d=d<0?d+12:d,s[j++-1]=d+48);a=!strcmp(s,"221222");}

Cobalah online!

Berdasarkan jawaban Perl.

Mengambil input sebagai string lebar.

Tidak Terkumpul:

int f(int *a){
	char s[9], b[9];
	int h, i, j;
	h = 0;
        for(i = 0; a[i] != NULL; i++){
		if(a[i] == '#'){
			b[i-h-1] += 1;
			h++;
		}
		else if(a[i] == 'b'){
			b[i-1-h] -= 1;
			h++;
		}
		else{
			b[i-h] = (a[i] * 13) >> 3;
		}
	}
	for(j = 1; j < 7; j++){
		int d = (b[j] - b[j-1]) % 12;
		d = d < 0? d + 12: d;
		s[j-1] = d + '0';
	}
	return strcmp(s, "221222") == 0;
}
Logern
sumber
170 byte
ceilingcat
2

[Bahasa Wolfram (Mathematica) + Paket Musik`], 114 byte

Saya suka musik dan menemukan ini menarik, tapi saya keluar bermain golf nyata ketika peluang golf kode ini turun sehingga pengajuan saya agak lambat.

Saya pikir saya akan mencoba ini dengan cara yang sama sekali berbeda, memanfaatkan pengetahuan musik yang sebenarnya. Ternyata paket musik Mathematica tahu frekuensi dasar dari not yang disebutkan. Pertama saya mengonversi string input menjadi urutan catatan bernama. Selanjutnya, saya mengambil rasio masing-masing not berturut-turut dan menggandakan setiap yang kurang dari 2 (untuk memperhitungkan pergeseran oktaf). Kemudian saya membandingkan rasio ini dengan rasio skala Ionia yang memiliki sekitar 6% perbedaan frekuensi antara setengah nada dan 12% antara nada penuh.

Lebih dari setengah byte yang dihabiskan di sini adalah untuk mengubah input menjadi simbol bernama.

.06{2,2,1,2,2,2}+1==Round[Ratios[Symbol[#~~"0"]&/@StringReplace[# ,{"b"->"flat","#"->"sharp"}]]/.x_/;x<1->2x,.01]&

Cobalah online!

Kelly Lowder
sumber
2

Python 3 , 175 136 134 114 112 byte

def f(t):r=[ord(x[0])//.6+ord(x[1:]or'"')%13-8for x in t];return[(y-x)%12for x,y in zip(r,r[1:])]==[2,2,1,2,2,2]

Cobalah online!


Implementasi satu-baris Python 3.

Terima kasih kepada @Arnauld untuk ide menghitung nada menggunakan pembagian dan modulo.
Terima kasih kepada @ Jo King untuk -39 byte.

cobaltp
sumber
1
136 bytes
Jo King
1

[Python] 269 202 byte

Perbaikan dari Jo King:

p=lambda z:"A BC D EF G".index(z[0])+"b #".index(z[1:]or' ')-1
def d(i,j):f=abs(p(i)-p(j));return min(f,12-f)
q=input().replace(' ','').split(',')
print([d(q[i],q[i+1])for i in range(6)]==[2,2,1,2,2,2])

Cobalah!

Tidak disatukan, dengan test driver:

tone = "A BC D EF G"   # tones in "piano" layout
adj = "b #"            # accidentals

def note_pos(note):
    if len(note) == 1:
        note += ' '
    n,a = note
    return tone.index(n) + adj[a]

def note_diff(i, j):
    x, y = note_pos(i), note_pos(j)
    diff = abs(x-y)
    return min(diff, 12-diff)

def is_scale(str):
    seq = str.replace(' ','').split(',')
    div = [note_diff(seq[i], seq[i+1]) for i in (0,1,2,3,4,5)]
    return div == [2,2,1,2,2,2]

case = [
("C, D, E, F, G, A, B", True),
("C#, D#, E#, F#, G#, A#, B#", True),
("Db, Eb, F, Gb, Ab, Bb, C", True),
("D, E, Gb, G, A, Cb, C#", True),
("Eb, E#, G, G#, Bb, B#, D", True),

("C, D#, E, F, G, A, B", False),
("Db, Eb, F, Gb, Ab, B, C", False),
("G#, E, F, A, B, D#, C", False),
("C#, C#, E#, F#, G#, A#, B#", False),
("Eb, E#, Gb, G#, Bb, B#, D", False),
]

for test, result in case:
    print(test + ' '*(30-len(test)), result, '\t',
          "valid" if is_scale(test) == result else "ERROR")
Memangkas
sumber
Ya, saya melihat ruang putih - masih ditanamkan dengan terlalu banyak PEP-8, saya khawatir. Saya tampaknya melewatkan sesuatu; apakah tautan eksekusi diperlukan di sini?
Prune
1
Padahal, jika Anda menginginkan tautan, 202 byte dengan beberapa golf cepat. Anda pasti bisa bermain golf lagi dengan mengubah ke format input yang berbeda
Jo King
Ah ... Saya terlalu terbiasa dengan Python mengembalikan ekspresi akhir sebagai nilai proses. Terima kasih atas petunjuk dan petunjuknya.
Prune
Anda bisa mendapatkan 156 byte jika Anda beralih ke suatu fungsi dengan mengambil daftar string. Selain itu, TIO memiliki pemformat otomatis di bagian tautan yang dapat Anda gunakan
Jo King
@JoKing, Anda dipersilakan untuk mengedit jawaban ini atau memposting jawaban Anda sendiri; berkomentar dengan tautan memisahkan peningkatan dengan satu level.
Prune
1

Ruby , 109 byte

->s{(0..11).any?{|t|s.map{|n|(w="Cef;DXg<E=Fhi>G j8A d9B:")[(w.index(""<<n.sum%107)/2-t)%12]}*''=='CfDX<=h'}}

Cobalah online!

GB
sumber