È una scala maggiore (o equivalente)?


16

sandbox

La scala maggiore (o scala ionica) è una delle scale musicali più comunemente usate, specialmente nella musica occidentale. È una delle scale diatoniche. Come molte scale musicali, è composto da sette note: l'ottava duplica la prima a doppia frequenza in modo da essere chiamata un'ottava più alta della stessa nota.

Le sette note musicali sono:

C, D, E, F, G, A, B , C (ripetuta ad esempio)

Una scala maggiore è una scala diatonica. Prendi la successione precedente di note come scala maggiore (In realtà, è la scala C maggiore) . La sequenza di intervalli tra le note di una scala maggiore è:

intero, intero, mezzo, intero, intero, intero, mezzo

dove "intero" sta per un tono intero (una curva a forma di U rossa nella figura) e "metà" sta per un semitono (una linea spezzata rossa nella figura).

inserisci qui la descrizione dell'immagine

In questo caso, da C a D esiste un tono intero , da D a E esiste un tono intero , da E a F esiste un mezzo tono, ecc ...

Abbiamo 2 componenti che influiscono sulla distanza del tono tra le note. Questi sono il simbolo Sharp (♯) e il simbolo piatto (♭).

Il simbolo Sharp (♯) aggiunge un mezzo tono alla nota. Esempio. Da C a D abbiamo detto che esiste un tono intero, se usiamo C♯ invece C allora da C♯ a D esiste mezzo tono.

Il simbolo Flat (♭) fa l'opposto del simbolo Sharp, sottrae il semitono dalla nota. Esempio: da D a E abbiamo detto che esiste un tono intero, se usiamo Db invece D quindi da Db a E esiste un tono e mezzo.

Per impostazione predefinita, da Nota a Nota esiste un tono intero ad eccezione di E to Fe B to Cin cui esiste solo mezzo tono.

Nota in alcuni casi l'uso di altezze enarmoniche può creare un equivalente di una scala maggiore. Un esempio di ciò è C#, D#, E#, F#, G#, A#, B#, C#dove E#e B#sono enarmonici, ma la scala segue la sequenza di una scala maggiore.


Sfida

Data una scala, genera un valore di verità se è una scala maggiore o equivalente, altrimenti genera un valore di falsa.

Regole

  • Metodo di I / O standard consentito
  • Si applicano le regole standard del
  • Non è necessario prendere in considerazione l'ottava nota. Supponiamo che l'input consisterà solo di 7 note
  • Supponiamo che non esistano il doppio piatto (♭♭), il doppio segno tagliente (♯♯) o il segno naturale (♮)

Casi 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

@Abigail Fondamentalmente sì. Hanno lo stesso tono anche se sono note diverse.
Luis felipe De jesus Munoz,

1
e Cx (o C ##) = D
SaggingRufus

1
A proposito, le bilance pentatoniche non hanno una lettera per ciascuna: v
Luis felipe De jesus Munoz

1
@Neil Le scale cromatiche non hanno lettere univoche e sono sicuro che esiste un tipo di scala che non segue un ordine crescente
Luis felipe De jesus Munoz

1
Dovrò votare questo perché @Neil lo ha declassato grazie mille
David Conrad

Risposte:


11

Perl 6 , 76 65 63 59 byte

-4 byte grazie a Phil H

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

Provalo online!

Spiegazione

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

Se hai intenzione di fare una differenza a coppie e modulo 12, non è necessario sottrarre 105; è solo un offset. -4 caratteri: tio.run/…
Phil H

@PhilH Sì, certo. Grazie!
nwellnhof,

È un modo davvero intelligente di mappare le note sui loro valori relativi, +1 da me!
Ha

10

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

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

Provalo online!

Come?

Ogni nota n viene convertita in un numero negativo in [118,71] con:

[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

Che dà:

  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

Calcoliamo le differenze a coppie modulo 12 tra questi valori.

La differenza più bassa possibile tra 2 note è 47 , quindi è sufficiente aggiungere 4×12=48 prima di applicare il modulo per assicurarsi che si ottenga un risultato positivo.

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

aNaN

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

i12


Ottimo approccio, molto più interessante della mia risposta
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'

Provalo online!

-19 byte grazie a Luis felipe
-6 byte grazie a 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']invece di 'C0D0EF0G0A0B'.split('')e +""invece di .toString()salvare alcuni byte
Luis felipe De jesus Munoz

x[1]=='#'|-(x[1]=='b')invece di x[1]=='#'?1:(x[1]=='b'?-1:0)salvare anche qualche byte
Luis felipe De jesus Munoz l'

@LuisfelipeDejesusMunoz Oh bello grazie! Non riesco a credere di aver dimenticato l'espansione dell'array e l'aggiunta di una stringa vuota
Skidsdev

"Se il delta è negativo, sostituirlo con 2" suona errato. Penso che tu debba prendere la differenza modulo 12.
nwellnhof

@nwellnhof Nei miei test, tutte le scale principali avevano o i delta corretti per cominciare, o, se si estendevano su un'ottava, avevano un delta a -10 invece di 2. Sostituire i delta negativi risolve questo. Non credo -10 % 12 == 2. Anche se vieni a pensarci, in alcuni casi potrebbe non riuscire ...
Skidsdev,

3

Dardo , 198 197 196 189 byte

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

Provalo online!

Porta allentata della vecchia risposta 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 byte usando operatori ternari per # / b
  • -1 byte usando ifs invece di ternari per gli spostamenti di scala
  • -7 byte grazie a @Kevin Cruijssen

Vecchia versione :

Dardo , 210 byte

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

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

Un passo intero è 2, un quarto è 1. Mod 12 nel caso si salti a un'ottava più alta. Scorre tutte le note e calcola la differenza tra la nota e la nota i-1. Concatena il risultato e dovrebbe aspettarsi 221222 (2 interi, 1 metà, 3 interi).

  • -2 byte non assegnando 0 a k
  • -4 byte usando j come stringa e non come elenco
  • -6 byte grazie a @Kevin Cruijssen rimuovendo il disordine non necessario negli anelli

Non conosco Dart, ma le parti sono simili a Java. Pertanto: il passaggio i=1a i=0può ridurre un byte passando for(;i<7;i++)a for(;++i<7;). Inoltre, le staffe {}possono essere rimossi intorno quel ciclo, mettendo la j+=...all'interno della terza parte del ciclo: for(;++i<7;j+='${(y[0]-y[1])%12}'). E un'ultima cosa sta cambiando return j=='221222';per return'221222'==j;sbarazzarsi dello spazio. -6 ( 210 byte ) dopo queste modifiche.
Kevin Cruijssen,

Grazie, non sapevo di quei trucchi per i loop
Elcan

NP. Nella tua nuova versione da 196 byte puoi anche giocare a golf a 189 byte cambiando if(k>9)k--;if(k>3)k--;in k-=k>3?k>9?2:1:0;e k+=m.length<2?0:m[1]=='#'?1:m[1]=='b'?-1:0;return k;in return m.length<2?k:m[1]=='#'?k+1:m[1]=='b'?k-1:k;. :)
Kevin Cruijssen l'

Dannazione, ho ancora molto da imparare sembra, grazie!
Elcan,

Bene, gioco a golf da 2,5 anni ormai, e persino ricevo sempre suggerimenti su come giocare a golf. :) Inizialmente è abbastanza facile perdere qualcosa da soli e con il tempo pensi a diversi modi di giocare a golf. :) I suggerimenti per giocare a golf in <tutte le lingue> potrebbero essere interessanti da leggere se non l'hai ancora fatto. E alcuni dei suggerimenti per giocare a golf a Java potrebbero essere applicabili anche a Dart, poiché i golf che ho fatto nelle tue risposte erano basati sulle mie conoscenze su Java, poiché questa è la prima volta che vedo Dart. ;)
Kevin Cruijssen l'

2

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

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

Provalo online!

Basato sulla risposta del Perl.

Accetta l'input come una stringa ampia.

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

[Pacchetto Wolfram Language (Mathematica) + Music`], 114 byte

Adoro la musica e l'ho trovato interessante, ma ero fuori a giocare a golf reale quando questa opportunità di golf del codice è arrivata al luccio, quindi la mia presentazione è un po 'tardiva.

Ho pensato di provarlo in un modo completamente diverso, utilizzando alcune conoscenze musicali attuali. Si scopre che il pacchetto musicale di Mathematica conosce la frequenza fondamentale delle note nominate. Per prima cosa converto la stringa di input in sequenza di note denominate. Successivamente, prendo i rapporti di ogni nota successiva e raddoppio qualsiasi sia inferiore a 2 (per tenere conto dello spostamento di ottava). Quindi confronto questi rapporti con i rapporti della scala ionica che ha circa una differenza di frequenza del 6% tra le mezze note e il 12% tra le note intere.

Più della metà dei byte trascorsi qui è di convertire l'input in simboli denominati.

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

Provalo online!


2

Python 3 , 175 136 134 114 112 byte

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]

Provalo online!


Un'implementazione di Python 3 da una riga.

Grazie a @Arnauld per l'idea di calcolare i toni usando divisione e modulo.
Grazie a @Jo King per -39 byte.



1

[Python] 269 202 byte

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

Provalo!

Ungolfed, con test driver:

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

Sì, vedo lo spazio bianco - ancora inculcato con troppo PEP-8, temo. Apparentemente mi mancava qualcosa; è richiesto un link di esecuzione qui?
Prugna

1
Tuttavia, se si desidera il collegamento, 202 byte con un po 'di golf veloce. Potresti sicuramente giocare ancora un po 'a golf cambiando in un diverso formato di input
Jo King,

Ah ... sono troppo abituato a Python che restituisce l'espressione finale come valore di processo. Grazie per i suggerimenti e i suggerimenti.
Pota il

È possibile ottenere 156 byte se si passa a una funzione prendendo un elenco di stringhe. Inoltre, TIO ha un formatter automatico nella sezione link che puoi usare
Jo King

@JoKing, sei il benvenuto per modificare questa risposta o pubblicare la tua; commentare con un collegamento separa i miglioramenti di un livello.
Pota il

1

Rubino , 109 byte

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.