S'agit-il d'une échelle majeure (ou équivalente)?

16

bac à sable

La gamme majeure (ou gamme ionienne) est l'une des gammes musicales les plus couramment utilisées, en particulier dans la musique occidentale. C'est l'une des échelles diatoniques. Comme de nombreuses gammes musicales, il est composé de sept notes: la huitième duplique la première à deux fois sa fréquence de sorte qu'elle s'appelle une octave supérieure de la même note.

Les sept notes de musique sont:

C, D, E, F, G, A, B , C (répété à titre d'exemple)

Une échelle majeure est une échelle diatonique. Prenez la succession précédente de notes comme une gamme majeure (en fait, c'est la gamme C majeur) . La séquence d'intervalles entre les notes d'une gamme majeure est:

entier, entier, moitié, entier, entier, entier, moitié

où "entier" représente un ton entier (une courbe en forme de U rouge sur la figure) et "demi" représente un demi-ton (une ligne rouge brisée sur la figure).

entrez la description de l'image ici

Dans ce cas, de C à D existe un ton entier , de D à E existe un ton entier , de E à F existe moitié ton, etc ...

Nous avons 2 composants qui affectent la distance de ton entre les notes. Ce sont le symbole Sharp (♯) et le symbole plat (♭).

Le symbole Sharp (♯) ajoute un demi-ton à la note. Exemple. De C à D, nous avons mentionné qu'il existe un ton entier, si nous utilisons C♯ à la place C, alors de C♯ à D existe un demi-ton.

Le symbole Flat (♭) fait l'opposé du symbole Sharp, il soustrait le demi-ton de la note. Exemple: De D à E, nous avons mentionné qu'il existe un ton entier, si nous utilisons Db à la place D, alors de Db à E existe un ton et demi.

Par défaut, de Note en Note existe une tonalité entière sauf pour E to FetB to C dans lequel n'existe qu'un demi-ton.

Notez que dans certains cas, l'utilisation des hauteurs enharmoniques peut créer un équivalent à une échelle majeure. Un exemple de ceci est C#, D#, E#, F#, G#, A#, B#, C#E#etB# sont enharmoniques mais l'échelle suit la séquence d'une échelle majeure.


Défi

Étant donné une échelle, émettez une valeur véridique s'il s'agit d'une échelle majeure ou équivalente, sinon émettez une valeur de falsey.

Règles

  • Méthode d'E / S standard autorisée
  • standard règles de s'appliquent
  • Vous n'avez pas besoin de prendre en considération la 8ème note. Supposons que l'entrée ne comprendra que 7 notes
  • Supposons que le double plat (♭♭), le double tranchant (♯♯) ou le signe naturel (♮) n'existent pas

Cas de test

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
la source
@Abigail Fondamentalement oui. Ils ont le même ton bien que ce soient des notes différentes.
Luis felipe De jesus Munoz
1
et Cx (ou C ##) = D
SaggingRufus
1
Btw, les gammes pentatoniques n'ont pas une de chaque lettre: v
Luis felipe De jesus Munoz
1
@Neil Les gammes chromatiques n'ont pas de lettres uniques et je suis sûr qu'il existe un type de gamme qui ne suit pas un ordre croissant
Luis felipe De jesus Munoz
1
Je vais devoir voter positivement parce que @Neil a voté contre, merci beaucoup
David Conrad

Réponses:

11

Perl 6 , 76 65 63 59 octets

-4 octets grâce à Phil H

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

Essayez-le en ligne!

Explication

*>>.&{ ... }  # 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
la source
Si vous voulez faire une différence par paire et modulo 12, vous n'avez pas besoin de soustraire 105; c'est juste un décalage. -4 caractères: tio.run/…
Phil H
@PhilH Oui, bien sûr. Merci!
nwellnhof
C'est une façon très intelligente de mapper les notes à leurs valeurs relatives, +1 de moi!
Sok
10

Node.js v10.9.0 , 78 76 71 69 octets

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

Essayez-le en ligne!

Comment?

Chaque note n est convertie en un nombre négatif en [118,71] avec:

[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

Qui donne:

  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

Nous calculons les différences par paires modulo 12 entre ces valeurs.

La différence la plus faible possible entre 2 notes est de 47 , il suffit donc d'ajouter 4×12=48 avant d'appliquer le modulo pour être sûr d'obtenir un résultat positif.

Parce que nous appliquons un modulo 12 , le décalage produit par a '#'est en fait 36mod12=0 demi-ton, tandis que le décalage produit par a 'b'est 38mod12=2 demi-tons.

uneNaN

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

je12

Arnauld
la source
Grande approche, beaucoup plus intéressante que ma réponse
Skidsdev
4

JavaScript (Node.js) , 150 131 125 octets

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'

Essayez-le en ligne!

-19 octets grâce à Luis felipe
-6 octets grâce à Shaggy

Non golfé:

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
la source
1
[...'C0D0EF0G0A0B']au lieu de 'C0D0EF0G0A0B'.split('')et +""au lieu de .toString()sauver quelques octets
Luis felipe De jesus Munoz
x[1]=='#'|-(x[1]=='b')au lieu de x[1]=='#'?1:(x[1]=='b'?-1:0)sauvegarder aussi quelques octets
Luis felipe De jesus Munoz
@LuisfelipeDejesusMunoz Oh gentil merci! Je ne peux pas croire que j'ai oublié l'extension du tableau et l'ajout d'une chaîne vide
Skidsdev
"Si delta est négatif, remplacez-le par 2" sonne mal. Je pense que vous devez prendre la différence modulo 12.
nwellnhof
@nwellnhof Dans mes tests, toutes les gammes principales avaient soit les deltas corrects pour commencer, soit, si elles s'étalaient sur une octave, avaient un delta à -10 plutôt que 2. Le remplacement des deltas négatifs corrige cela. Je ne pense pas -10 % 12 == 2. Bien que
j'y
3

Dart , 198 197 196 189 octets

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

Essayez-le en ligne!

Port lâche de l'ancienne réponse 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 octet en utilisant des opérateurs ternaires pour # / b
  • -1 octet en utilisant ifs au lieu de ternaires pour les changements d'échelle
  • -7 octets grâce à @Kevin Cruijssen

Ancienne version :

Fléchette , 210 octets

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

Essayez-le en ligne!

Non golfé:

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

Une étape entière est 2, un quart est 1. Mod 12 si vous passez à une octave supérieure. Itère toutes les notes et calcule la différence entre la ième note et la i-1ème note. Concatène le résultat et devrait attendre 221222 (2 entiers, 1 moitié, 3 entiers).

  • -2 octets en n'affectant pas 0 à k
  • -4 octets en utilisant j comme chaîne et non comme liste
  • -6 octets grâce à @Kevin Cruijssen en supprimant l'encombrement inutile dans les boucles
Elcan
la source
Je ne connais pas Dart, mais les parties sont similaires à Java. Par conséquent: changer i=1en i=0peut réduire un octet en changeant for(;i<7;i++)en for(;++i<7;). De plus, les supports {}peuvent être retirés autour de cette boucle, en mettant l' j+=...intérieur de la troisième partie de la boucle: for(;++i<7;j+='${(y[0]-y[1])%12}'). Et une dernière chose est en train de changer return j=='221222';pour return'221222'==j;se débarrasser de l'espace. -6 ( 210 octets ) après ces modifications.
Kevin Cruijssen
Merci, je ne connaissais pas ces trucs pour les boucles
Elcan
Np. Dans votre nouvelle version de 196 octets, vous pouvez également la jouer à 189 octets en changeant if(k>9)k--;if(k>3)k--;pour k-=k>3?k>9?2:1:0;et k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;vers return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen
Merde, j'ai encore beaucoup à apprendre, semble-t-il, merci!
Elcan
Eh bien, je joue au golf depuis 2,5 ans maintenant, et même moi, je reçois tout le temps des conseils sur les choses. :) Il est assez facile de rater quelque chose vous-même au départ, et avec le temps, vous pensez à différentes façons de jouer au golf. :) Des conseils pour jouer au golf dans <toutes les langues> peuvent être intéressants à lire si vous ne l'avez pas encore fait. Et certains des conseils pour jouer au golf à Java pourraient également être applicables à Dart, car les golfs que j'ai faits dans vos réponses étaient basés sur mes connaissances en Java, car c'est la première fois que je vois Dart. ;)
Kevin Cruijssen
2

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

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

Essayez-le en ligne!

Basé sur la réponse Perl.

Prend l'entrée comme une chaîne large.

Non golfé:

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
la source
170 octets
Plafond
2

[Wolfram Language (Mathematica) + Music` package], 114 octets

J'adore la musique et j'ai trouvé ça intéressant, mais je jouais au vrai golf quand cette opportunité de golf à code est tombée, donc ma soumission est un peu tardive.

J'ai pensé que j'essaierais cela d'une manière totalement différente, en utilisant des connaissances musicales réelles. Il s'avère que le package musical de Mathematica connaît la fréquence fondamentale des notes nommées. Je convertis d'abord la chaîne d'entrée en séquence de notes nommées. Ensuite, je prends les ratios de chaque note successive et double celle qui est inférieure à 2 (pour tenir compte du décalage d'octave). Ensuite, je compare ces ratios aux ratios de l'échelle ionienne qui a à peu près une différence de fréquence de 6% entre les demi-notes et 12% entre les notes complètes.

Plus de la moitié des octets dépensés ici sont destinés à convertir l'entrée en symboles nommés.

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

Essayez-le en ligne!

Kelly Lowder
la source
2

Python 3 , 175 136 134 114 112 octets

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]

Essayez-le en ligne!


Une implémentation Python 3 à une ligne.

Merci à @Arnauld pour l'idée de calculer les tons en utilisant la division et le modulo.
Merci à @Jo King pour -39 octets.

cobaltp
la source
1
136 octets
Jo King
1

[Python] 269 202 octets

Améliorations de 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])

Essayez!

Non golfé, avec pilote d'essai:

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")
Prune
la source
Oui, je vois l'espace blanc - toujours inculqué avec trop de PEP-8, je le crains. J'ai apparemment manqué quelque chose; un lien d'exécution est-il requis ici?
Prune
1
Cependant, si vous voulez le lien, 202 octets avec un peu de golf. Vous pouvez certainement jouer au golf en changeant de format d'entrée
Jo King
Ah ... Je suis trop habitué à ce que Python renvoie l'expression finale comme valeur de processus. Merci pour les pointeurs et les astuces.
Prune
Vous pouvez obtenir 156 octets si vous passez à une fonction prenant une liste de chaînes. En outre, TIO a un formateur automatique dans la section des liens que vous pouvez utiliser
Jo King
@JoKing, vous êtes parfaitement invités à modifier cette réponse ou à publier la vôtre; commenter avec un lien sépare les améliorations d'un niveau.
Prune