Czy jest to skala główna (lub równoważna)?

16

Piaskownica

Skala główna (lub skala jońska) jest jedną z najczęściej używanych skal muzycznych, szczególnie w muzyce zachodniej. Jest to jedna ze skal diatonicznych. Podobnie jak wiele skal muzycznych, składa się z siedmiu nut: ósma duplikuje pierwszą z podwójną częstotliwością, tak że nazywa się ją wyższą oktawą tej samej nuty.

Siedem nut to:

C, D, E, F, G, A, B , C (powtórzone np. W celach)

Skala główna to skala diatoniczna. Weź poprzednią sekwencję nut jako dużą skalę (w rzeczywistości jest to skala C-dur) . Sekwencja odstępów między nutami dużej skali jest następująca:

całe, całe, pół, całe, całe, całe, pół

gdzie „całość” oznacza cały ton (czerwona krzywa w kształcie litery U na rysunku), a „połowa” oznacza półton (czerwona przerywana linia na rysunku).

wprowadź opis zdjęcia tutaj

W tym przypadku od C do D istnieje cały ton, od D do E istnieje cały ton, od E do F. pół tonu, itp ...

Mamy 2 elementy, które wpływają na odległość tonów między nutami. Są to symbol ostry (♯) i płaski symbol (♭).

Symbol Sharp (♯) dodaje półton do nuty. Przykład. Od C do D wspomnieliśmy, że istnieje cały ton, jeśli użyjemy C♯ zamiast C, to od C♯ do D istnieje półton.

Płaski symbol (♭) działa odwrotnie niż ostry symbol, odejmuje pół tonu od nuty. Przykład: od D do E wspomnieliśmy, że istnieje cały ton, jeśli użyjemy Db zamiast D, to od Db do E istnieje półtora tonu.

Domyślnie od Nuty do Nuty istnieje cały ton, z wyjątkiem E to Fi B to Cw którym istnieje tylko półton.

Uwaga: w niektórych przypadkach użycie boisk enharmonicznych może stworzyć odpowiednik Skali Głównej. Przykładem tego jest C#, D#, E#, F#, G#, A#, B#, C#gdzie E#i B#są enharmoniczne, ale skala jest zgodna z sekwencją głównej skali.


Wyzwanie

Biorąc pod uwagę skalę, wyprowadzaj prawdziwą wartość, jeśli jest to Skala główna lub równoważna, w przeciwnym razie wyprowadzaj wartość falsey.

Zasady

  • Dozwolona standardowa metoda we / wy
  • Obowiązują standardowe zasady
  • Nie musisz brać pod uwagę ósmej nuty. Załóżmy, że dane wejściowe będą się składać tylko z 7 nut
  • Załóżmy, że podwójne płaskie (♭♭), podwójne ostre (♯♯) lub naturalny znak (♮) nie istnieją

Przypadki testowe

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
źródło
@Abigail Zasadniczo tak. Mają ten sam ton, chociaż są to różne nuty.
Luis Felipe De Jesus Munoz
1
i Cx (lub C ##) = D
SaggingRufus
1
Przy okazji, skale pentatoniczne nie mają jednej z każdej litery: v
Luis felipe De jesus Munoz
1
@Neil Wagi chromatyczne nie mają unikalnych liter i jestem pewien, że istnieje rodzaj skali, która nie jest zgodna z rosnącą kolejnością
Luis felipe De jesus Munoz
1
Będę musiał to zagłosować, ponieważ @Neil przegłosował to bardzo dziękuję
David Conrad

Odpowiedzi:

11

Perl 6 , 76 65 63 59 bajtów

-4 bajty dzięki Philowi ​​H.

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

Wypróbuj online!

Wyjaśnienie

*>>.&{ ... }  # 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
źródło
Jeśli zamierzasz zrobić różnicę parami i modulo 12, nie musisz odejmować 105; to tylko przesunięcie. -4 znaki: tio.run/…
Phil H
@PhilH Tak, oczywiście. Dzięki!
nwellnhof,
To naprawdę sprytny sposób mapowania notatek na ich względne wartości +1 ode mnie!
Sok
10

Node.js 10.9.0 , 78 76 71 69 bajtów

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

Wypróbuj online!

W jaki sposób?

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

Co daje:

  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) półtonów.

zaNaN

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

ja12)

Arnauld
źródło
Świetne podejście, o wiele bardziej interesujące niż moja odpowiedź
Skidsdev,
4

JavaScript (Node.js) , 150 131 125 bajtów

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'

Wypróbuj online!

-19 bajtów dzięki Luisowi Felipe
-6 bajtów dzięki Shaggy

Nie golfowany:

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
źródło
1
[...'C0D0EF0G0A0B']zamiast 'C0D0EF0G0A0B'.split('')i +""zamiast .toString()oszczędzać niektóre bajty
Luis Felipe De Jesus Munoz
x[1]=='#'|-(x[1]=='b')zamiast x[1]=='#'?1:(x[1]=='b'?-1:0)oszczędzać też trochę bajtów
Luis Felipe De Jesus Munoz
@LuisfelipeDejesusMunoz Och, dziękuję! Nie mogę uwierzyć, że zapomniałem o rozszerzeniu tablicy i dodaniu pustego ciągu
Skidsdev
„Jeśli delta jest ujemna, zamień ją na 2” brzmi źle. Myślę, że musisz wziąć różnicę modulo 12.
nwellnhof
@nwellnhof W moich testach wszystkie główne skale miały albo na początku prawidłowe delty, albo, jeśli obejmowały oktawę, miały jedną deltę na -10 zamiast 2. Zastępowanie delt ujemnych naprawia to. Nie sądzę -10 % 12 == 2. Chociaż o tym pomyślę, w niektórych przypadkach może się to nie powieść ...
Skidsdev,
3

Dart , 198 197 196 189 bajtów

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

Wypróbuj online!

Luźny port starej odpowiedzi Perla 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 bajt przy użyciu operatorów trójskładnikowych dla # / b
  • -1 bajt przy użyciu ifs zamiast trójskładników do przesunięć skali
  • -7 bajtów dzięki @Kevin Cruijssen

Stara wersja :

Dart , 210 bajtów

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

Wypróbuj online!

Nie golfowany:

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

Cały krok to 2, jedna czwarta to 1. Mod 12 na wypadek, gdybyś skoczył na wyższą oktawę. Iteruje wszystkie nuty i oblicza różnicę między i-tą nutą a i-1. Łączy wynik i należy spodziewać się 221222 (2 całe, 1 połowa, 3 całości).

  • -2 bajty, nie przypisując 0 do k
  • -4 bajty przy użyciu j jako ciągu, a nie listy
  • -6 bajtów dzięki @Kevin Cruijssen poprzez usunięcie niepotrzebnego bałaganu w pętlach
Elcan
źródło
Nie znam Dart, ale części są podobne do Javy. Dlatego: zmiana i=1na i=0może zmniejszyć bajt poprzez zmianę for(;i<7;i++)na for(;++i<7;). Ponadto, uchwyty {}mogą być usunięte wokół tej pętli, przez umieszczenie j+=...wewnątrz trzeciej części pętli: for(;++i<7;j+='${(y[0]-y[1])%12}'). I ostatnia sprawa zmienia return j=='221222';się return'221222'==j;pozbyć przestrzeni. -6 ( 210 bajtów ) po tych modyfikacjach.
Kevin Cruijssen
Dzięki, nie wiedziałem o tych sztuczkach dla pętli
Elcan
Np. W swojej nowej 196-bajtowej wersji możesz także zagrać w golfa do 189 bajtów , zmieniając if(k>9)k--;if(k>3)k--;na k-=k>3?k>9?2:1:0;i k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;na return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen
Cholera, wciąż muszę się wiele nauczyć, dzięki!
Elcan
Cóż, gram w golfa już od 2,5 roku i nawet dostaję wskazówki dotyczące golfa przez cały czas. :) Na początku bardzo łatwo coś przeoczyć, az czasem zastanawiasz się nad różnymi sposobami gry w golfa. :) Wskazówki dotyczące gry w golfa w <wszystkich językach> mogą być interesujące, jeśli jeszcze tego nie zrobiłeś. A niektóre Porady dotyczące gry w golfa w Javie mogą być również przydatne w Dart, ponieważ golfy, które zrobiłem w twoich odpowiedziach, były oparte na mojej wiedzy o Javie, ponieważ po raz pierwszy widzę Dart. ;)
Kevin Cruijssen
2

C (gcc) , -DA=a[i]+ 183 = 191 bajtów

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

Wypróbuj online!

Na podstawie odpowiedzi Perla.

Pobiera dane wejściowe jako szeroki ciąg.

Nie golfowany:

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
źródło
170 bajtów
ceilingcat
2

[Wolfram Language (Mathematica) + pakiet muzyczny], 114 bajtów

Uwielbiam muzykę i uważam to za interesujące, ale grałem w prawdziwego golfa, kiedy ta okazja do gry w golfa spadła na szczupaka, więc moje poddanie jest trochę spóźnione.

Pomyślałem, że spróbuję tego zupełnie inaczej, wykorzystując trochę wiedzy muzycznej. Okazuje się, że pakiet muzyczny Mathematica zna podstawową częstotliwość nazwanych nut. Najpierw przekształcam ciąg wejściowy w sekwencję nazwanych notatek. Następnie biorę proporcje każdej kolejnej nuty i podwajam te, które są mniejsze niż 2 (aby uwzględnić przesunięcie oktawy). Następnie porównuję te stosunki ze stosunkami skali jońskiej, która ma w przybliżeniu 6% różnicy częstotliwości między półtonami i 12% między pełnymi nutami.

Ponad połowa wydanych tutaj bajtów służy do konwersji danych wejściowych na nazwane symbole.

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

Wypróbuj online!

Kelly Lowder
źródło
2

Python 3 , 175 136 134 114 112 bajtów

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]

Wypróbuj online!


Jednowierszowa implementacja Python 3.

Podziękowania dla @Arnauld za pomysł obliczania tonów za pomocą podziału i modulo.
Dzięki @Jo King za -39 bajtów.

kobalt
źródło
1
136 bajtów
Jo King
1

[Python] 269 202 bajtów

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

Spróbuj!

Niegolfowany, ze sterownikiem testowym:

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")
Suszona śliwka
źródło
Tak, widzę białą przestrzeń - obawiam się, że wciąż jest za dużo PEP-8. Najwyraźniej coś mi umknęło; czy wymagany jest tutaj link do wykonania?
Prune
1
Chociaż, jeśli chcesz link, 202 bajty z szybkim golfem. Na pewno możesz trochę golfa, przechodząc na inny format wejściowy
Jo King
Ach ... Jestem zbyt przyzwyczajony, że Python zwraca końcowe wyrażenie jako wartość procesu. Dzięki za wskazówki i wskazówki.
Prune
Możesz uzyskać 156 bajtów, jeśli przełączysz się na funkcję przyjmującą listę ciągów znaków. Ponadto TIO ma automatyczny formatator w sekcji linków, którego możesz użyć
Jo King
@JoKing, możesz z łatwością edytować tę odpowiedź lub opublikować własną; komentowanie za pomocą linku rozdziela ulepszenia o jeden poziom.
Przycinaj
1

Rubin , 109 bajtów

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

Wypróbuj online!

GB
źródło