Ist das eine Dur-Tonleiter (oder gleichwertig)?

16

Sandkasten

Die Dur-Tonleiter (oder Ionian-Tonleiter) ist eine der am häufigsten verwendeten Tonleitern, insbesondere in der westlichen Musik. Es ist eine der diatonischen Skalen. Wie viele musikalische Skalen besteht es aus sieben Noten: Die achte dupliziert die erste mit der doppelten Frequenz, so dass es eine höhere Oktave derselben Note heißt.

Die sieben Noten sind:

C, D, E, F, G, A, B , C (zum Beispiel wiederholt)

Eine Hauptskala ist eine diatonische Skala. Nehmen Sie die vorherige Notenfolge als Dur-Tonleiter (Tatsächlich ist es die Tonleiter C-Dur) . Die Reihenfolge der Intervalle zwischen den Noten einer Dur-Tonleiter ist:

ganz, ganz, halb, ganz, ganz, ganz, halb

Dabei steht "ganz" für einen ganzen Ton (eine rote U-förmige Kurve in der Figur) und "halb" für einen Halbton (eine rote gestrichelte Linie in der Figur).

Bildbeschreibung hier eingeben

In diesem Fall existiert von C nach D ein ganzer Ton, von D nach E existiert ein ganzer Ton, von E nach F existiert ein halber Ton, etc ...

Wir haben 2 Komponenten, die den Tonabstand zwischen den Noten beeinflussen. Dies sind das scharfe Symbol (♯) und das flache Symbol (♭).

Das Sharp-Symbol (♯) fügt der Note einen Halbton hinzu. Beispiel. Von C nach D haben wir erwähnt, dass es einen ganzen Ton gibt. Wenn wir C♯ anstelle von C verwenden, dann gibt es von C♯ nach D einen halben Ton.

Das flache Symbol (♭) ist das Gegenteil des scharfen Symbols und subtrahiert den Halbton von der Note. Beispiel: Von D nach E haben wir erwähnt, dass es einen ganzen Ton gibt. Wenn wir stattdessen D verwenden, dann gibt es von Db nach E eineinhalb Töne.

Standardmäßig ist von Note zu Note ein ganzer Ton vorhanden, mit Ausnahme von E to Fund B to Cin denen nur ein Halbton vorhanden ist.

Hinweis in einigen Fällen mit enharmonic Teilungen kann eine äquivalent zu einem Dur - Tonleiter erstellen. Ein Beispiel hierfür ist, C#, D#, E#, F#, G#, A#, B#, C#wo E#und B#sind Enharmonie, aber die Skala folgt der Reihenfolge einer Dur-Skala.


Herausforderung

Geben Sie bei einer gegebenen Skala einen Wahrheitswert aus, wenn es sich um eine Hauptskala oder ein Äquivalent handelt, andernfalls geben Sie einen Falschwert aus.

Regeln

  • Standard-E / A-Methode zulässig
  • Standard gelten
  • Sie müssen die Achtelnote nicht berücksichtigen. Angenommen, die Eingabe besteht nur aus 7 Noten
  • Angenommen, es gibt kein doppeltes flaches (♭♭), doppeltes scharfes (♯♯) oder natürliches Vorzeichen (♮)

Testfälle

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
quelle
@Abigail Grundsätzlich ja. Sie haben den gleichen Ton, obwohl es sich um unterschiedliche Noten handelt.
Luis Felipe De Jesus Munoz
1
und Cx (oder C
##
1
Übrigens haben pentatonische
1
@ Neil Chromatische Skalen haben keine eindeutigen Buchstaben und ich bin sicher, es gibt eine Art von Skala , die nicht in aufsteigender Reihenfolge folgt
Luis Felipe de Jesus Munoz
1
Ich muss das hochstufen, weil @Neil es heruntergestuft hat. Vielen Dank
David Conrad

Antworten:

11

Perl 6 , 76 65 63 59 Bytes

-4 Bytes dank Phil H

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

Probieren Sie es online!

Erläuterung

*>>.&{ ... }  # 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
quelle
Wenn Sie eine paarweise Differenz und Modulo 12 machen wollen, müssen Sie nicht 105 subtrahieren; Es ist nur ein Versatz. -4 Zeichen: tio.run/…
Phil H
@ PHILH Ja, natürlich. Vielen Dank!
Nwellnhof
Das ist eine sehr clevere Methode, um die Notizen auf ihre relativen Werte abzubilden, +1 von mir!
Sok
10

Node.js 10.9.0 , 78 76 71 69 Bytes

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

Probieren Sie es online!

Wie?

Jede Note n wird in [-118,-71]mit:

[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

Welches gibt:

  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

Wir berechnen die paarweisen Differenzen modulo 12 zwischen diesen Werten.

Der kleinstmögliche Unterschied zwischen 2 Noten ist -47 , es reicht also aus, ihn hinzuzufügen4×12=48bevor Sie das Modulo anwenden, um ein positives Ergebnis zu.

Da wir ein Modulo 12 anwenden , ist der von a erzeugte Versatz '#'tatsächlich 36mod12=0 Halbton, während der von a erzeugte Versatz 'b'ist38mod12=2 Halbtöne.

Wir verwenden die Eingabevariable einNaN

Für eine größere Skala sollten wir [NaN,2,2,1,2,2,2] .

Wir verwenden den Zähler ich , um den 4. Wert mit 1 zu vergleichen, anstatt2

Arnauld
quelle
Großartiger Ansatz, viel interessanter als meine Antwort
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'

Probieren Sie es online!

-19 Bytes dank Luis Felipe
-6 Bytes dank 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';
}
Skidsdev
quelle
1
[...'C0D0EF0G0A0B']statt 'C0D0EF0G0A0B'.split('')und +""statt .toString(), um einige Bytes zu speichern
Luis Felipe De Jesus Munoz
x[1]=='#'|-(x[1]=='b')anstatt auch ein x[1]=='#'?1:(x[1]=='b'?-1:0)paar Bytes zu speichern
Luis Felipe De Jesus Munoz
@LuisfelipeDejesusMunoz Oh, danke schön! Ich kann nicht glauben, dass ich die Array-Erweiterung und das Hinzufügen eines leeren Strings
vergessen habe
"Wenn Delta negativ ist, ersetzen Sie es durch 2" klingt falsch. Ich denke, Sie müssen den Unterschied Modulo 12 nehmen.
Nwellnhof
@nwellnhof In meinen Tests hatten alle wichtigen Skalen entweder die richtigen Deltas oder, wenn sie eine Oktave überspannten, ein Delta bei -10 anstatt bei 2. Das Ersetzen negativer Deltas behebt das. Ich glaube nicht -10 % 12 == 2. Obwohl dies in einigen Fällen scheitern könnte ...
Skidsdev
3

Dart , 198 197 196 189 Bytes

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

Probieren Sie es online!

Lose Portierung der alten Perl 6-Antwort /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 mit ternären Operatoren für # / b
  • -1 Byte durch Verwendung von ifs anstelle von ternaries für die Skalierungsverschiebungen
  • -7 Bytes dank @Kevin Cruijssen

Alte Version :

Dart , 210 Bytes

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

Probieren Sie es online!

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

Ein ganzer Schritt ist 2, ein Viertel ist 1. Mod 12 für den Fall, dass Sie zu einer höheren Oktave springen. Durchläuft alle Noten und berechnet den Unterschied zwischen der i-ten Note und der i-1-ten Note. Verkettet das Ergebnis und sollte 221222 (2 ganze, 1 halbe, 3 ganze) erwarten.

  • -2 Bytes, indem k keine 0 zugewiesen wird
  • -4 Bytes mit j als String und nicht als Liste
  • -6 Bytes dank @Kevin Cruijssen, indem unnötiges Durcheinander in Schleifen beseitigt wird
Elcan
quelle
Ich kenne Dart nicht, aber Teile ähneln Java. Deshalb: Wechsel i=1zu i=0können , indem ein Byte reduzieren for(;i<7;i++)zu for(;++i<7;). Darüber hinaus können die Klammern {}können um diese Schleife entfernt werden, indem die Umsetzung j+=...in dem dritten Teil des Loop: for(;++i<7;j+='${(y[0]-y[1])%12}'). Und eine letzte Sache ändert return j=='221222';sich return'221222'==j;, um den Raum loszuwerden. -6 ( 210 Byte ) nach diesen Änderungen.
Kevin Cruijssen
Danke, wusste nichts über diese Tricks für die Loops
Elcan
Np. In Ihrer neuen 196-Byte-Version können Sie auch auf 189 Byte Golf spielen, indem Sie if(k>9)k--;if(k>3)k--;zu k-=k>3?k>9?2:1:0;und k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;zu wechseln return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen
Verdammt, ich muss noch viel lernen, danke!
Elcan
Nun, ich spiele seit 2,5 Jahren Golf und bekomme sogar immer wieder Tipps zum Golfen. :) Es ist ziemlich einfach, selbst etwas zu übersehen, und mit der Zeit überlegt man sich verschiedene Möglichkeiten zum Golfen. :) Tipps zum Golfen in <allen Sprachen> sind möglicherweise interessant, wenn Sie sie noch nicht gelesen haben. Und einige der Tipps für das Golfen in Java könnten auch für Dart gelten, da die in Ihren Antworten aufgeführten Golfplätze auf meinen Java-Kenntnissen basierten, da ich Dart zum ersten Mal sehe. ;)
Kevin Cruijssen
2

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

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

Probieren Sie es online!

Basierend auf der Perl-Antwort.

Nimmt die Eingabe als breite Zeichenfolge.

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;
}
Logern
quelle
170 Bytes
Ceilingcat
2

[Wolfram Language (Mathematica) + Musikpaket], 114 Bytes

Ich liebe Musik und fand das interessant, aber ich war gerade dabei, richtig Golf zu spielen, als diese Codegolf-Gelegenheit auf mich zukam, so dass mein Beitrag etwas verspätet ist.

Ich dachte, ich würde es auf eine ganz andere Weise versuchen und dabei tatsächlich Musikkenntnisse nutzen. Es stellt sich heraus, dass das Musikpaket von Mathematica die Grundfrequenz der genannten Noten kennt. Zuerst konvertiere ich die Eingabezeichenfolge in eine Folge benannter Noten. Als nächstes nehme ich die Verhältnisse jeder aufeinanderfolgenden Note und verdopple alle, die kleiner als 2 sind (um die Oktavverschiebung zu berücksichtigen). Dann vergleiche ich diese Verhältnisse mit den Verhältnissen der Ionischen Skala, die einen Frequenzunterschied von ungefähr 6% zwischen halben Noten und 12% zwischen vollen Noten aufweisen.

Mehr als die Hälfte der hier verbrachten Bytes dient dazu, die Eingabe in benannte Symbole umzuwandeln.

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

Probieren Sie es online!

Kelly Lowder
quelle
2

Python 3 , 175 136 134 114 112 Bytes

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]

Probieren Sie es online!


Eine einzeilige Python 3-Implementierung.

Vielen Dank an @Arnauld für die Idee, Töne mit Division und Modulo zu berechnen.
Vielen Dank an @Jo King für -39 Bytes.

Cobaltp
quelle
1
136 Bytes
Jo King
1

[Python] 269 202 Bytes

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

Versuch es!

Ungolfed, mit Testfahrer:

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")
Pflaume
quelle
Ja, ich sehe den weißen Raum - leider immer noch mit zu viel PEP-8 eingeschärft. Ich habe anscheinend etwas verpasst; Ist hier ein Ausführungslink erforderlich?
Beschneiden Sie den
1
Wenn Sie jedoch die Verknüpfung möchten, müssen Sie 202 Bytes mit ein wenig schnellem Golf spielen. Sie könnten definitiv mehr Golf spielen, wenn Sie zu einem anderen Eingabeformat wechseln
Jo King,
Ah ... ich bin es auch gewohnt, dass Python den endgültigen Ausdruck als Prozesswert zurückgibt. Danke für die Hinweise und Hinweise.
Beschneiden Sie den
Sie können 156 Bytes erhalten, wenn Sie zu einer Funktion wechseln, die eine Liste von Zeichenfolgen verwendet. Außerdem hat TIO einen Auto-Formatierer im Link-Bereich, den Sie verwenden können
Jo King,
@JoKing, Sie können diese Antwort gerne bearbeiten oder Ihre eigene veröffentlichen. Das Kommentieren mit einem Link trennt die Verbesserungen um eine Ebene.
Beschneiden Sie den