Đây có phải là một quy mô lớn (hoặc tương đương)?


16

Hộp cát

Thang đo chính (hay thang âm Ionia) là một trong những thang âm nhạc được sử dụng phổ biến nhất, đặc biệt là trong âm nhạc phương Tây. Đây là một trong những thang đo diatonic. Giống như nhiều thang âm nhạc, nó được tạo thành từ bảy nốt nhạc: nốt thứ tám nhân đôi âm đầu tiên với tần số gấp đôi để nó được gọi là quãng tám cao hơn của cùng một nốt nhạc.

Bảy nốt nhạc là:

C, D, E, F, G, A, B , C (lặp lại cho mục đích ví dụ)

Một thang đo chính là thang đo diatonic. Lấy sự kế thừa trước đó của ghi chú làm thang đo chính (Trên thực tế, đó là thang điểm C Major) . Trình tự các khoảng giữa các nốt của thang đo chính là:

toàn bộ, toàn bộ, một nửa, toàn bộ, toàn bộ, toàn bộ, một nửa

trong đó "toàn bộ" là viết tắt của toàn bộ tông màu (một đường cong hình chữ u màu đỏ trong hình) và "một nửa" là viết tắt của một nửa cung (một đường gãy màu đỏ trong hình).

nhập mô tả hình ảnh ở đây

Trong trường hợp này, từ C đến D tồn tại toàn bộ âm, từ D đến E tồn tại toàn bộ âm, từ E đến F tồn tại một nửa âm, v.v ...

Chúng tôi có 2 thành phần ảnh hưởng đến khoảng cách âm giữa các nốt. Đó là biểu tượng Sharp (♯) và biểu tượng phẳng (♭).

Biểu tượng Sharp (♯) thêm một nửa âm cho ghi chú. Thí dụ. Từ C đến D, chúng tôi đã đề cập rằng tồn tại toàn bộ âm, nếu chúng ta sử dụng C♯ thay vì C thì từ C♯ đến D tồn tại một nửa âm.

Biểu tượng Flat (♭) làm ngược lại với biểu tượng Sharp, nó trừ đi một nửa âm từ ghi chú. Ví dụ: Từ D đến E, chúng tôi đã đề cập đến việc tồn tại toàn bộ âm, nếu chúng tôi sử dụng Db thay vì D thì từ Db đến E tồn tại một âm và một nửa.

Theo mặc định, từ Ghi chú đến Lưu ý tồn tại toàn bộ âm ngoại trừ E to FB to Ctrong đó chỉ tồn tại một nửa âm.

Lưu ý trong một số trường hợp sử dụng các nốt tăng cường có thể tạo ra một tỷ lệ tương đương với Thang đo chính. Một ví dụ về điều này là C#, D#, E#, F#, G#, A#, B#, C#ở đâu E#B#được tăng cường nhưng thang đo tuân theo trình tự của Thang đo chính.


Thử thách

Đưa ra một thang đo, xuất ra một giá trị trung thực nếu nó là Thang đo chính hoặc tương đương, nếu không thì xuất ra một giá trị falsey.

Quy tắc

  • Phương pháp I / O tiêu chuẩn được phép
  • Luật tiêu chuẩn được áp dụng
  • Bạn không cần phải xem xét lưu ý thứ 8. Giả sử đầu vào sẽ chỉ bao gồm 7 ghi chú
  • Giả sử hai mặt phẳng (♭♭), sắc nét gấp đôi (♯♯) hoặc dấu tự nhiên (♮) không tồn tại

Các trường hợp thử nghiệm

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

@ Abigail Về cơ bản là có. Chúng có cùng tông mặc dù chúng là những nốt khác nhau.
Luis felipe De jesus Munoz

1
và Cx (hoặc C ##) = D
SaggingRufus

1
Btw, Pentatonic vảy không có một trong mỗi chữ cái: v
Luis felipe De jesus Munoz

1
@Neil Thang màu sắc không có chữ cái duy nhất và tôi chắc chắn có một loại thang đo không tuân theo thứ tự tăng dần
Luis felipe De jesus Munoz

1
Tôi sẽ phải nâng cao điều này bởi vì @Neil đã đánh giá thấp nó cảm ơn bạn rất nhiều
David Conrad

Câu trả lời:


11

Perl 6 , 76 65 63 59 byte

-4 byte nhờ Phil H

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

Hãy thử trực tuyến!

Giải trình

*>>.&{ ... }  # 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

Nếu bạn sẽ thực hiện một sự khác biệt theo cặp và modulo 12, bạn không cần phải trừ 105; nó chỉ là một sự bù đắp -4 ký tự: tio.run/ Kẻ
Phil H

@PhilH Vâng, tất nhiên. Cảm ơn!
nwellnhof

Đó là một cách thực sự thông minh để ánh xạ các ghi chú theo các giá trị tương đối của chúng, +1 từ tôi!
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)

Hãy thử trực tuyến!

Làm sao?

Mỗi ghi chú n được chuyển đổi thành số âm trong [-118,-71] với:

[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

Cung cấp cho:

  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

Chúng tôi tính toán sự khác biệt theo cặp modulo 12 giữa các giá trị này.

Sự khác biệt thấp nhất có thể có giữa 2 ghi chú là -47 , do đó, đủ để thêm 4×12= =48 trước khi áp dụng modulo để đảm bảo rằng chúng tôi nhận được kết quả dương tính.

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

aNaN

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

i12


Cách tiếp cận tuyệt vời, thú vị hơn nhiều so với câu trả lời của tôi
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'

Hãy thử trực tuyến!

-19 byte nhờ Luis felipe
-6 byte nhờ Shaggy

Ung dung:

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';
}

1
[...'C0D0EF0G0A0B']thay vì 'C0D0EF0G0A0B'.split('')+""thay vì .toString()để lưu một số byte
Luis felipe De jesus Munoz

x[1]=='#'|-(x[1]=='b')thay vì x[1]=='#'?1:(x[1]=='b'?-1:0)lưu một số byte quá
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz ơi cảm ơn rất nhiều! Tôi không thể tin rằng tôi đã quên việc mở rộng mảng và thêm một chuỗi trống
Skidsdev

"Nếu delta là âm, thay thế nó bằng 2" nghe có vẻ sai. Tôi nghĩ rằng bạn cần phải có sự khác biệt modulo 12.
nwellnhof

@nwellnhof Trong các thử nghiệm của tôi, tất cả các thang đo chính đều có các đồng bằng chính xác bắt đầu bằng, hoặc, nếu chúng kéo dài quãng tám, có một delta ở -10 thay vì 2. Thay thế các deltas âm sửa chữa điều đó. Tôi không nghĩ -10 % 12 == 2. Mặc dù nghĩ về điều này nhưng điều này có thể thất bại trong một số trường hợp ...
Skidsdev

3

Phi tiêu , 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;}

Hãy thử trực tuyến!

Cổng lỏng lẻo của câu trả lời Perl 6 cũ /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 bằng cách sử dụng các toán tử ternary cho # / b
  • -1 byte bằng cách sử dụng ifs thay vì ternaries cho thang đo dịch chuyển
  • -7 byte nhờ @Kevin Cruijssen

Phiên bản cũ :

Phi tiêu , 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;}

Hãy thử trực tuyến!

Ung dung:

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;
}

Toàn bộ một bước là 2, một phần tư là 1. Mod 12 trong trường hợp bạn nhảy lên quãng tám cao hơn. Lặp lại thông qua tất cả các ghi chú và tính toán sự khác biệt giữa ghi chú thứ i và ghi chú thứ i-1. Kết quả kết quả và nên mong đợi 221222 (2 toàn bộ, 1 nửa, 3 wholes).

  • -2 byte bằng cách không gán 0 cho k
  • -4 byte bằng cách sử dụng j làm Chuỗi và không phải là Danh sách
  • -6 byte nhờ @Kevin Cruijssen bằng cách loại bỏ sự lộn xộn không cần thiết trong các vòng lặp

Tôi không biết Dart, nhưng các phần tương tự như Java. Do đó: thay đổi i=1để i=0có thể giảm một byte bằng cách thay đổi for(;i<7;i++)thành for(;++i<7;). Ngoài ra, các dấu ngoặc {}có thể được loại bỏ xung quanh vòng lặp đó, bằng cách đặt j+=...bên trong phần thứ ba của vòng lặp : for(;++i<7;j+='${(y[0]-y[1])%12}'). Và một điều cuối cùng là thay đổi return j=='221222';để return'221222'==j;thoát khỏi không gian. -6 ( 210 byte ) sau những sửa đổi này.
Kevin Cruijssen

Cảm ơn, không biết về những mánh khóe cho các vòng lặp
Elcan

Np. Trong phiên bản 196 byte mới của bạn, bạn cũng có thể đánh gôn thành 189 byte bằng cách thay đổi if(k>9)k--;if(k>3)k--;thành k-=k>3?k>9?2:1:0;k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;sang return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen

Chết tiệt, tôi vẫn còn nhiều điều phải học, cảm ơn!
Elcan

Chà, tôi đã chơi golf được 2,5 năm rồi và thậm chí tôi còn nhận được những lời khuyên về mọi thứ để chơi golf mọi lúc. :) Ban đầu, bạn rất dễ bỏ lỡ điều gì đó và theo thời gian, bạn nghĩ về những cách khác nhau để chơi gôn. :) Mẹo chơi gôn bằng <tất cả các ngôn ngữ> có thể thú vị để đọc qua nếu bạn chưa có. Và một số Mẹo để chơi gôn trong Java cũng có thể được áp dụng trong Dart, vì các tôi đã làm trong câu trả lời của bạn dựa trên kiến ​​thức Java của tôi, vì đây là lần đầu tiên tôi nhìn thấy 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");}

Hãy thử trực tuyến!

Dựa trên câu trả lời Perl.

Đưa đầu vào dưới dạng một chuỗi rộng.

Ung dung:

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;
}


2

[Ngôn ngữ Wolfram (Mathicala) + Gói âm nhạc], 114 byte

Tôi yêu âm nhạc và thấy điều này thú vị, nhưng tôi đã ra ngoài chơi golf thực sự khi cơ hội chơi golf mã này giảm xuống vì vậy trình của tôi hơi chậm trễ.

Tôi hình dung tôi sẽ thử điều này theo một cách hoàn toàn khác, sử dụng một số kiến ​​thức âm nhạc thực tế. Hóa ra gói nhạc của Mathematica biết tần số cơ bản của các nốt nhạc được đặt tên. Đầu tiên tôi chuyển đổi chuỗi đầu vào thành chuỗi các ghi chú được đặt tên. Tiếp theo, tôi lấy tỷ lệ của từng nốt liên tiếp và nhân đôi bất kỳ số nào nhỏ hơn 2 (để tính đến sự thay đổi quãng tám). Sau đó, tôi so sánh các tỷ lệ này với các tỷ lệ của thang đo Ionia có chênh lệch tần số khoảng 6% giữa một nửa nốt và 12% giữa các nốt đầy đủ.

Hơn một nửa số byte được sử dụng ở đây là để chuyển đổi đầu vào thành các ký hiệu được đặt tên.

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

Hãy thử trực tuyến!


2

Con trăn 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]

Hãy thử trực tuyến!


Một triển khai Python 3 một lớp.

Cảm ơn @Arnauld về ý tưởng tính toán âm bằng cách sử dụng phép chia và modulo.
Cảm ơn @Jo King cho -39 byte.



1

[Con trăn] 269 202 byte

Những cải tiến từ 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])

Thử nó!

Ungolfed, với trình điều khiển thử nghiệm:

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

Vâng, tôi thấy khoảng trắng - vẫn bị khắc sâu với quá nhiều PEP-8, tôi sợ. Tôi dường như đã bỏ lỡ một cái gì đó; một liên kết thực hiện cần thiết ở đây?
Prune

1
Mặc dù, nếu bạn muốn liên kết, 202 byte với một số thao tác chơi gôn nhanh. Bạn chắc chắn có thể chơi gôn nhiều hơn bằng cách thay đổi sang một định dạng đầu vào khác
Jo King

À ... Tôi đã quá quen với việc Python trả về biểu thức cuối cùng làm giá trị tiến trình. Cảm ơn các gợi ý và gợi ý.
Prune

Bạn có thể nhận được 156 byte nếu bạn chuyển sang một hàm lấy danh sách các chuỗi. Ngoài ra, TIO có trình định dạng tự động trong phần liên kết mà bạn có thể sử dụng
Jo King

@JoKing, bạn hoàn toàn hoan nghênh chỉnh sửa câu trả lời này hoặc đăng bài của riêng bạn; bình luận với một liên kết phân tách các cải tiến theo một cấp độ.
Prune

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.