Це основна шкала (чи еквівалент)?


16

Пісочниця

Основна шкала (або іонічна шкала) - одна з найбільш часто використовуваних музичних шкал, особливо у західній музиці. Це одна з діатонічних шкал. Як і багато музичні шкали, він складається з семи нот: восьма дублює першу на подвійну її частоту, так що вона називається вищою октавою тієї ж ноти.

Сім музичних нот:

C, D, E, F, G, A, B , C (повторюється для прикладу)

Основна шкала - діатонічна шкала. Візьміть попередню послідовність нот як основну шкалу (Насправді, це масштаб С-мажор) . Послідовність інтервалів між нотами головного масштабу становить:

цілий, цілий, наполовину, цілий, цілий, цілий, наполовину

де "ціле" позначає цілий тон (червона u-образна крива на фігурі), а "половина" означає півтон (червона зламана лінія на малюнку).

введіть тут опис зображення

В цьому випадку, від С до D існувати цілий тон, від D до Е існує ціла тон, від Е до F існує половину тон, і т.д. ...

У нас є 2 компоненти, які впливають на тональну відстань між нотами. Це символ Різкий (♯) і плоский символ (♭).

Символ різкої різкості (♯) додає ноті наполовину тон. Приклад. З C до D ми згадували, що існує цілий тон, якщо ми використовуємо C♯ замість C, то від C♯ до D існує півтони.

Символ «Плоский» (do) робить протилежний символу «Різкий», він віднімає половину тону від ноти. Приклад: від D до E ми згадували, що існує цілий тон, якщо ми використовуємо Db замість D, то від Db до E існує півтора тона.

За замовчуванням, від ноти до ноти існує цілий тон , за винятком , E to Fі B to Cв якому тільки половина тон існує.

Зверніть увагу, що в деяких випадках використання енгармонічних смол може створити еквівалент основній шкалі. Прикладом цього є, C#, D#, E#, F#, G#, A#, B#, C#де E#і B#є енгармонічними, але шкала відповідає послідовності великої шкали.


Виклик

Враховуючи масштаб, виведіть триєдне значення, якщо воно є основною шкалою або еквівалентом, інакше виведіть значення фальси.

Правила

  • Дозволений стандартний метод вводу / виводу
  • Діють стандартні правила
  • Не потрібно брати до уваги восьму записку. Припустимо, що вхід складається лише з 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, пентатонічні ваги не мають по одній букві: v
Luis felipe De jesus Munoz

1
@Neil Хроматичні ваги не мають унікальних літер, і я впевнений, що існує тип шкали, яка не відповідає порядку зростання
Луїс феліпе Де ісус Муноз

1
Мені доведеться підтримати це, тому що @Neil відхилив це велике спасибі
Девід Конрад

Відповіді:


11

Perl 6 , 76 65 63 59 байт

-4 байти завдяки Філу Н

{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 ч .
Філ Х

@PhilH Так, звичайно. Спасибі!
nwellnhof

Це дійсно розумний спосіб відображення приміток до їх відносних значень, +1 від мене!
Сік

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)

Спробуйте в Інтернеті!

Як?

Кожна примітка н перетворюється на від'ємне число у [-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 між цими значеннями.

Найменша різниця між 2 нотами -47 , тому досить додати 4×12=48 перед застосуванням модуля щоб переконатися, що ми отримаємо позитивний результат.

Оскільки ми застосовуємо модуль 12 , зміщення, яке виробляється a '#', насправді становить 36мод12=0 півтона, тоді як зміщення, вироблене а, 'b'становить 38мод12=2 півтони.

аNaN .

[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 байт завдяки Луїсу Феліпе
-6 байт завдяки Шаггі

Безголівки:

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)зберегти кілька байтів
Луїс felipe De jesus Munoz

@LuisfelipeDejesusMunoz О, приємно дякую! Не можу повірити, що забув про розширення масиву та додав порожню рядок
Skidsdev

"Якщо дельта негативна, замініть її на 2" звучить неправильно. Я думаю, вам потрібно прийняти різницю за модулем 12.
nwellnhof

@nwellnhof У моїх тестах усі основні шкали або мали правильні дельти для початку, або, якщо вони охоплювали октаву, мали одну дельту на -10, а не 2. Заміна негативних дельт виправлень це. Я не думаю -10 % 12 == 2. Хоча придумайте це, в деяких випадках це може бути невдалим ...
Skidsdev

3

Дарт , 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;}

Спробуйте в Інтернеті!

Безголівки:

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-й нотою та i-й нотою. Зв'язує результат і слід очікувати 221222 (2 цілих, 1 половина, 3 цілих).

  • -2 байти, не призначаючи 0 до k
  • -4 байти, використовуючи j як рядок, а не список
  • -6 байтів завдяки @Kevin Cruijssen, видаливши зайві безладу в петлях

Я не знаю Дарт, але частини схожі на 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 байт ) після цих модифікацій.
Кевін Кройсейсен

Дякую, не знав про ті хитрощі для циклів
Елкан

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;. :)
Кевін Кройсейсен

Чорт, мені ще багато чого навчитися, здається, дякую!
Елькан

Ну, я займаюся гольфом вже 2,5 роки, і навіть постійно отримую поради щодо речей, якими можна займатися. :) Спочатку пропустити щось самостійно досить просто, а з часом ви думаєте про різні способи гри в гольф. :) Поради щодо гольфу на <всіх мовах> можуть бути цікавими для прочитання, якщо ви ще цього не зробили. І деякі поради щодо гри в гольф на Java можуть бути застосовні також у Dart, оскільки гольфи, які я робив у ваших відповідях, базувались на моїх знаннях Java, оскільки я вперше бачу Дарт. ;)
Кевін Круїссен

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.

Вводиться як широкий рядок.

Безголівки:

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]&

Спробуйте в Інтернеті!



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

Спробуй це!

Безумовно, з тест-драйвером:

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 байти з швидким гольфом. Ви, безумовно, можете пограти ще трохи, змінивши інший формат введення
Jo King

Ах ... Я занадто звик, щоб Python повертав остаточний вираз як значення процесу. Дякуємо за покажчики та підказки.
Чорнослив

Ви можете отримати 156 байт, якщо перейти на функцію, що містить список рядків. Також у TIO є автоматичний форматник у розділі посилань, який ви можете використовувати
Jo King

@JoKing, ви можете редагувати цю відповідь або опублікувати свою; коментування за посиланням відокремлює поліпшення на один рівень.
Чорнослив

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.