นี่คือมาตราส่วนหลัก (หรือเทียบเท่า) หรือไม่


16

Sandbox

สเกลหลัก (หรือสเกลโยนก) เป็นหนึ่งในสเกลดนตรีที่ใช้กันมากที่สุดโดยเฉพาะในดนตรีตะวันตก มันเป็นหนึ่งในเกล็ดคู่ เช่นเดียวกับเครื่องชั่งน้ำหนักดนตรีจำนวนมากมันประกอบด้วยโน้ตเจ็ด: แปดที่ซ้ำกันเป็นครั้งแรกที่สองเท่าของความถี่เพื่อที่จะเรียกว่าคู่ที่สูงขึ้นของโน้ตเดียวกัน

โน้ตดนตรีทั้งเจ็ด ได้แก่ :

C, D, E, F, G, A, B , C (ซ้ำเพื่อวัตถุประสงค์ตัวอย่าง)

สเกลที่สำคัญคือสเกลคู่ ใช้สืบทอดก่อนหน้าของบันทึกเป็นขนาดใหญ่(ที่จริงมันเป็นขนาด C เมเจอร์) ลำดับของช่วงเวลาระหว่างบันทึกย่อของมาตราส่วนหลักคือ:

ทั้งหมดทั้งหมดครึ่งทั้งหมดทั้งหมดทั้งหมดครึ่ง

โดยที่ "ทั้ง" หมายถึงน้ำเสียงทั้งหมด (เส้นโค้งรูปตัวยูสีแดงในภาพ) และ "ครึ่ง" หมายถึงน้ำเสียงกึ่งกลาง (เส้นสีแดงแตกในรูป)

ป้อนคำอธิบายรูปภาพที่นี่

ในกรณีนี้จาก C ถึง D มีทั้งโทนจาก D ถึง E มีทั้งโทนจาก E ถึง F มีอยู่ครึ่งโทน ฯลฯ

เรามี 2 องค์ประกอบที่มีผลต่อระยะห่างของเสียงระหว่างโน้ต เหล่านี้คือสัญลักษณ์ชาร์ป (♯) และสัญลักษณ์แบน (♭)

สัญลักษณ์ชาร์ป (♯) เพิ่มครึ่งเสียงให้กับโน้ต ตัวอย่าง. จาก C ถึง D เราพูดถึงว่ามีน้ำเสียงทั้งหมดถ้าเราใช้C♯แทน C ดังนั้นจากC♯ถึง D จะมีครึ่งเสียง

สัญลักษณ์แบบแบน (♭) ทำตรงข้ามกับสัญลักษณ์ชาร์ปซึ่งจะลบครึ่งเสียงออกจากบันทึกย่อ ตัวอย่าง: จาก D ถึง E เราพูดถึงว่ามีทั้งโทนถ้าเราใช้ Db แทน D จากนั้นจาก Db ถึง E จะมีน้ำเสียงครึ่ง

โดยค่าเริ่มต้นจาก Note ถึง Note จะมีทั้งโทนเสียงยกเว้นE to FและB to Cมีเพียงครึ่งเสียงเท่านั้น

หมายเหตุในบางกรณีการใช้สนามเพิ่มประสิทธิภาพสามารถสร้างเทียบเท่ากับ Major Scale ตัวอย่างของสิ่งนี้คือC#, D#, E#, F#, G#, A#, B#, C#ที่E#และB#เป็นแบบเสริม แต่ระดับตามลำดับของเมเจอร์สเกล


ท้าทาย

กำหนดสเกลเอาท์พุทค่าความจริงถ้ามันเป็นสเกลเมเจอร์หรือเทียบเท่ามิฉะนั้นเอาท์พุทค่าเท็จ

กฎระเบียบ

  • อนุญาตให้ใช้วิธี I / O มาตรฐาน
  • ใช้กฎมาตรฐานของ
  • คุณไม่จำเป็นต้องคำนึงถึงโน้ตที่ 8 สมมติว่าอินพุตจะประกอบด้วย 7 บันทึกเท่านั้น
  • สมมติว่าแบนสองครั้ง (♭♭), คมสองเท่า (♯♯) หรือสัญญาณธรรมชาติ (♮) ไม่มีอยู่

กรณีทดสอบ

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 โดยทั่วไปใช่ พวกเขามีโทนเสียงเดียวกันแม้ว่าจะเป็นโน้ตที่แตกต่างกัน
Luis felipe De jesus Munoz

1
และ Cx (หรือ C ##) = D
SaggingRufus

1
Btw เครื่องชั่ง Pentatonic ไม่มีหนึ่งในตัวอักษรแต่ละตัว: v
Luis felipe De jesus Munoz

1
@Neil เครื่องชั่งสีไม่มีตัวอักษรที่ไม่ซ้ำกันและฉันแน่ใจว่ามีประเภทของเครื่องชั่งที่ไม่ปฏิบัติตามคำสั่งจากน้อยไปมาก
Luis felipe De jesus Munoz

1
ฉันจะต้องโหวตเพราะ @Neil ลงคะแนนขอบคุณมาก
เดวิดคอนราด

คำตอบ:


11

Perl 6 , 76 65 63 59 ไบต์

-4 ไบต์ขอบคุณ Phil H

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

ลองออนไลน์!

คำอธิบาย

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

หากคุณกำลังทำผลต่างแบบคู่และโมดูโล 12 คุณไม่จำเป็นต้องลบ 105 มันเป็นเพียงการชดเชย -4 chars: tio.run/…
Phil H

@ ฟิลใช่แน่นอน ขอบคุณ!
nwellnhof

นั่นเป็นวิธีที่ฉลาดมากในการจับคู่โน้ตกับค่าที่สัมพันธ์กัน +1 จากฉัน!
Sok

10

Node.js v10.9.0 , 78 76 71 69 ไบต์

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

ลองออนไลน์!

อย่างไร?

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

ซึ่งจะช่วยให้:

  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

474×12=48

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

aNaN

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

i12


วิธีการที่ยอดเยี่ยมและน่าสนใจยิ่งกว่าคำตอบของฉัน
Skidsdev

4

JavaScript (Node.js) , 150 131 125 ไบต์

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'

ลองออนไลน์!

-19 ไบต์ขอบคุณ Luis felipe
-6 ไบต์ขอบคุณ Shaggy

Ungolfed:

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']แทน'C0D0EF0G0A0B'.split('')และ+""แทนที่จะ.toString()บันทึกบางไบต์
Luis felipe De jesus Munoz

x[1]=='#'|-(x[1]=='b')แทนที่จะx[1]=='#'?1:(x[1]=='b'?-1:0)บันทึกไบต์ด้วย
Luis felipe De jesus Munoz

@LuisfelipeDejesusMunoz โอ้ขอบคุณมาก! ฉันไม่อยากจะเชื่อเลยว่าฉันลืมเรื่องการขยายอาเรย์และเพิ่มสตริงว่าง
Skidsdev

"ถ้าเดลต้าเป็นลบให้แทนที่ด้วย 2" ฟังผิด ฉันคิดว่าคุณต้องใช้ความแตกต่างแบบโมดูโล 12
nwellnhof

@nwellnhof ในการทดสอบของฉันเครื่องชั่งที่สำคัญทั้งหมดมีเดลตาที่ถูกต้องที่จะเริ่มต้นด้วยหรือถ้าพวกเขาทอดอ็อกเทฟมีเดลต้าหนึ่งที่ -10 แทนที่จะเป็น 2 แทนที่เดลต้าเชิงลบที่แก้ไข -10 % 12 == 2ฉันไม่คิดว่า แม้ว่าจะมาคิดว่ามันนี้อาจล้มเหลวในบางกรณี ...
Skidsdev

3

Dart , 198 197 196 189 ไบต์

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

ลองออนไลน์!

พอร์ตหลวมของ Perl 6 คำตอบ/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 ไบต์โดยใช้ตัวดำเนินการประกอบสำหรับ # / b
  • -1 ไบต์โดยใช้ ifs แทน ternaries สำหรับการเลื่อนสเกล
  • -7 ไบต์ขอบคุณ @Kevin Cruijssen

เวอร์ชั่นเก่า :

โผ , 210 ไบต์

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

ลองออนไลน์!

Ungolfed:

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

ขั้นตอนทั้งหมดคือ 2 ไตรมาสคือ 1 แก้ไข 12 ในกรณีที่คุณข้ามไปยังระดับเสียงสูง วนซ้ำทุกโน้ตและคำนวณความแตกต่างระหว่างโน้ตที่มีและโน้ต i-1 ต่อผลลัพธ์และควรคาดหวัง 221222 (ทั้ง 2, 1 ครึ่ง, 3 wholes)

  • -2 ไบต์โดยไม่กำหนด 0 ถึง k
  • -4 ไบต์โดยใช้ j เป็นสตริงและไม่ใช่รายการ
  • -6 ไบต์ขอบคุณ @Kevin Cruijssen โดยการลบความยุ่งเหยิงที่ไม่จำเป็นในลูป

ฉันไม่รู้ Dart แต่ส่วนต่าง ๆ คล้ายกับ Java ดังนั้น: การเปลี่ยนแปลงi=1ที่จะi=0สามารถลดไบต์โดยการเปลี่ยนไปfor(;i<7;i++) for(;++i<7;)นอกจากนี้ในวงเล็บ{}สามารถถอดออกรอบห่วงว่าโดยการวางภายในส่วนที่สามของวง:j+=... for(;++i<7;j+='${(y[0]-y[1])%12}')และสิ่งสุดท้ายที่เปลี่ยนreturn j=='221222';ไปreturn'221222'==j;เพื่อกำจัดพื้นที่ -6 ( 210 bytes )หลังจากการแก้ไขเหล่านี้
Kevin Cruijssen

ขอบคุณไม่ทราบเกี่ยวกับลูกเล่นเหล่านั้นสำหรับลูป
Elcan

Np ในรุ่นใหม่ 196 ไบต์ของคุณคุณยังสามารถกอล์ฟไปยัง189 ไบต์โดยการเปลี่ยนif(k>9)k--;if(k>3)k--;ไปk-=k>3?k>9?2:1:0;และจะk+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k; return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;:)
Kevin Cruijssen

ประณามฉันยังมีอีกมากที่จะเรียนรู้ดูเหมือนว่าขอบคุณ!
Elcan

ตอนนี้ฉันเล่นกอล์ฟมา 2.5 ปีแล้วและฉันก็ยังได้รับคำแนะนำเกี่ยวกับสิ่งต่าง ๆ ในการเล่นกอล์ฟตลอดเวลา :) มันค่อนข้างง่ายที่จะคิดถึงบางสิ่งบางอย่างในตอนแรกและในเวลาที่คุณคิดเกี่ยวกับวิธีการเล่นกอล์ฟที่แตกต่างกัน :) เคล็ดลับสำหรับการเล่นกอล์ฟใน <ทุกภาษา>อาจน่าสนใจหากคุณยังไม่ได้อ่าน และเคล็ดลับบางประการสำหรับการเล่นกอล์ฟใน Javaอาจใช้งานได้ใน Dart เนื่องจากสนามกอล์ฟที่ฉันทำในคำตอบของคุณขึ้นอยู่กับความรู้เกี่ยวกับ Java ของฉันเนื่องจากนี่เป็นครั้งแรกที่ฉันเห็น Dart ;)
Kevin Cruijssen

2

C (gcc) , -DA=a[i]+ 183 = 191 ไบต์

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

ลองออนไลน์!

ตามคำตอบ Perl

รับอินพุตเป็นสตริงกว้าง

Ungolfed:

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

[ภาษา Wolfram (Mathematica) + แพคเกจ Music`], 114 ไบต์

ฉันรักดนตรีและพบว่าสิ่งนี้น่าสนใจ แต่ฉันก็ออกไปเล่นกอล์ฟจริงเมื่อโอกาสที่รหัสกอล์ฟลงมาหอกดังนั้นการส่งของฉันจึงค่อนข้างล่าช้า

ฉันคิดว่าฉันจะลองวิธีนี้ต่างออกไปโดยสิ้นเชิงโดยใช้ความรู้ด้านดนตรีที่แท้จริง ปรากฎว่าแพ็คเกจดนตรีของ Mathematica รู้ถึงความถี่พื้นฐานของโน้ตที่มีชื่อ ก่อนอื่นฉันจะแปลงสตริงอินพุตให้เป็นลำดับของโน้ตที่มีชื่อ ต่อไปฉันใช้อัตราส่วนของแต่ละโน้ตที่ต่อเนื่องกันแล้วเพิ่มเป็นสองเท่าของค่าที่น้อยกว่า 2 (เพื่อให้ได้ระดับการเปลี่ยนระดับแปดเสียง) จากนั้นฉันก็เปรียบเทียบอัตราส่วนเหล่านี้กับอัตราส่วนของระดับไอโอเนียนซึ่งมีความแตกต่างความถี่ 6% ระหว่างโน้ตครึ่งหนึ่งและ 12% ระหว่างโน้ตเต็ม

มากกว่าครึ่งหนึ่งของจำนวนไบต์ที่ใช้ในที่นี้คือการแปลงอินพุตเป็นสัญลักษณ์ที่มีชื่อ

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

ลองออนไลน์!


2

Python 3 , 175 136 134 114 112 ไบต์

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]

ลองออนไลน์!


การใช้งาน Python 3 แบบซับเดี่ยว

ขอบคุณ @Arnauld สำหรับแนวคิดในการคำนวณเสียงโดยใช้การหารและโมดูโล
ขอบคุณ @Jo King สำหรับ -39 ไบต์



1

[Python] 269 202 ไบต์

การปรับปรุงจาก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])

ลองมัน!

Ungolfed พร้อมคนขับทดสอบ:

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

ใช่ฉันเห็นพื้นที่สีขาว - ยังคงปลูกฝังด้วย PEP-8 มากเกินไปฉันกลัว เห็นได้ชัดว่าฉันพลาดบางสิ่งบางอย่าง; จำเป็นต้องมีลิงค์ดำเนินการที่นี่หรือไม่
พรุน

1
ถึงแม้ว่าถ้าคุณต้องการลิงค์ แต่เพียง202 ไบต์ก็สามารถเล่นกอล์ฟได้อย่างรวดเร็ว คุณสามารถตีกอล์ฟได้มากกว่านี้โดยเปลี่ยนเป็นรูปแบบอินพุตอื่น
โจคิง

อ่า ... ฉันคุ้นเคยกับ Python มากที่สุดที่จะคืนค่านิพจน์สุดท้ายให้เป็นค่าของกระบวนการ ขอบคุณสำหรับคำแนะนำและคำแนะนำ
พรุน

คุณสามารถรับ156 ไบต์หากคุณสลับไปยังฟังก์ชันที่รับรายการสตริง นอกจากนี้ TIO ยังมีตัวจัดรูปแบบอัตโนมัติในส่วนลิงก์ที่คุณสามารถใช้ได้
Jo King

@JoKing คุณสามารถแก้ไขคำตอบหรือโพสต์ของคุณเองได้อย่างสมบูรณ์แบบ การแสดงความคิดเห็นด้วยลิงก์จะแยกการปรับปรุงตามระดับหนึ่ง
พรุน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.