La dicotomia minore-maggiore


15

Dato un elenco di accordi etichettarli come 'Maggiore' o 'Minore'.

Ingresso

L'input sarà un elenco di accordi, uno per riga, composto da 3 note separate da uno spazio. Ogni nota sarà composta dal nome della nota in maiuscolo ( A- G) e da un accidentale opzionale ( #o b). Gli accordi possono essere in qualsiasi inversione (ovvero le note possono essere in qualsiasi ordine).

Produzione

Se l'accordo è maggiore, produce "Major". Se l'accordo è minore, produce "Minor". Se l'accordo non è né maggiore né minore, genera una riga vuota.

Esempio

Ingresso

C E G
F Ab C
C Eb Gb
E G B
Db F Ab
Bb G D
D A Gb

Produzione

Major
Minor

Minor
Major
Minor
Major

Script di test

Come in alcune delle mie precedenti domande, ho nuovamente macellato alcuni script di test originariamente creati da Joey e Ventero per fornire alcuni casi di test per questa domanda:

Uso: ./test [your program and its arguments]

Rewards

Ogni voce che posso verificare che soddisfa le specifiche, supera i test e ha ovviamente avuto qualche tentativo di giocare a golf riceverà un mio voto (quindi per favore fornisci le istruzioni per l'uso con la tua risposta). La soluzione più breve entro la fine del 13/10/2012 sarà accettata come vincitrice.

Una piccola teoria

Per quelli di voi che non hanno conoscenze di teoria musicale, ecco abbastanza informazioni per essere in grado di competere.

Un accordo maggiore o minore è composto da tre note che sono separate da uno specifico schema di semitoni. Se consideriamo la radice (nota di fondo) dell'accordo 0, allora un accordo maggiore è il pattern 0-4-7 e un accordo minore è il pattern 0-3-7. Le cose sono rese più imbarazzanti dal fatto che alcune note sono un semitono a parte e alcune sono un tono a parte. La diffusione dei semitoni da Ab- G#è la seguente:

G#/Ab A A#/Bb B/Cb B#/C C#/Db D D#/Eb E/Fb E#/F F#/Gb G G#/Ab
  0   1   2    3     4    5   6   7    8     9    10  11  12

G#/Absignifica che G#è la stessa nota di Ab. Da questo possiamo vedere che l'accordo Ab C Ebè un accordo maggiore e che Ab Cb Ebè minore.

A complicare ulteriormente le cose, l'accordo Eb Cb Abè considerato essere lo stesso Ab Cb Eb, Cb Eb Abe Cb Ab Eb, e così via. Ognuna di queste variazioni è ancora un accordo minore.


2
Penso che il tuo bash tester abbia bisogno di input e di risposte attese scambiate.
flodel,

@flodel Sì, hai ragione. Mi dispiace, l'ho corretto ora. Dovrò verificare che anche lo script di test Powershell non abbia lo stesso problema.
Gareth,

Risposte:


3

GolfScript, 83 caratteri

n%{' '%{1\{'A#BC D EF G'?+}/.}%$(+2/{~- 12%}%.(+.(+]$0=.$]10,7>?'MMaijnoorr

'>2%}%

Questa è una prima soluzione rapida; Sono sicuro che questo può essere ulteriormente migliorato. Passa la suite di test bash, dopo aver corretto l'errore segnalato da flodel nei commenti.

Modifica 1: Hai salvato 5 caratteri con un modo più breve per riconoscere i modelli di accordi maggiori e minori canonizzati.

Modifica 2: Hai salvato altri 2 caratteri con una codifica di output più compatta ispirata alla soluzione di grc. (Grazie!) Come effetto collaterale, il codice ora stampa una riga vuota dopo l'output, ma il cablaggio di test sembra accettarlo, quindi immagino che sia OK. :)

Ecco come funziona:

  • Il ciclo esterno n%{ }%n*divide semplicemente l'input in righe, esegue il codice all'interno delle parentesi graffe per ogni riga e unisce i risultati con nuove righe.

  • ' '%divide ogni riga in una matrice di note. Per ciascuna di quelle note, 1\{'A#BC D EF G'?+}/quindi converte quella nota in un numero di semitono cercando ciascuno dei suoi caratteri nella stringa 'A#BC D EF G'e sommando le posizioni (che sarà -1 per qualsiasi carattere non trovato nella stringa, incluso in particolare b). (Sono sicuro di aver già visto questo trucco usato prima.) Infine, .duplica ogni numero, in modo che, alla fine del ciclo, ad esempio l'ingresso F Ab Csia stato trasformato in [9 9 0 0 4 4].

  • Quindi ordiniamo le note con $, spostiamo la prima nota alla fine con (+e dividiamo l'array in coppie con 2/, in modo che ora assomigli ad esempio [[9 0] [0 4] [4 9]]. Quindi {~- 12%}%mappa ogni coppia di note nella sua differenza modulo 12, trasformando la nostra matrice di esempio in [9 8 7].

  • Successivamente, .(+crea una copia dell'array e ruota i suoi elementi a sinistra di una posizione. Lo facciamo due volte e raccogliamo le copie in un array con ], in modo che il nostro esempio ora assomigli [[9 8 7] [8 7 9] [7 9 8]].

  • Quindi ordiniamo questo array di matrici con $e prendiamo il primo elemento - in questo caso [7 9 8]- con 0=. Quindi creiamo una copia di questo array ( .), lo ordiniamo ( $), raccogliamo sia l'array non ordinato che l'array non ordinato in un altro array di array ( ]) e cerchiamo la prima occorrenza dell'array [7 8 9](che è scritta 10,7>per salvare due caratteri ) dentro.

  • Questo ci dà sia 0(se l'array non ordinato era [7 8 9], e quindi l'accordo è maggiore), 1(se l'array non ordinato era una permutazione di [7 8 9], che, dato che il suo primo elemento deve essere più piccolo, può essere solo [7 9 8], rendendo l'accordo minore) o -1(se anche l'array ordinato non è uguale [7 8 9]).

  • Questo numero viene quindi utilizzato come indice iniziale nella stringa "MMaijnoorr\n\n"(in cui gli \ns sono indicati come avanzamenti di riga effettivi nel codice), da cui prendiamo quel carattere e ogni secondo successivo come output. Se l'indice è -1, partiamo dall'ultimo carattere della stringa, che è solo un avanzamento riga.


Bella spiegazione. Sto avendo la stessa difficoltà che mi sembra di avere sempre con GolfScript: posso invocare una riga alla volta con cui provare echo "G# B# Eb" | ruby golfscript.rb ilmari.gsma come posso eseguire lo script di test su di esso? Ci ho provato ./test ruby golfscript.rb ilmari.gsma non ce l'avevo. (Ti ho già dato un +1 perché ovviamente funziona, ma sono solo curioso)
Gareth,

1
@Gareth: sembra che sia un bug nello script bash test - non gestisce correttamente più argomenti. Per risolverlo, sostituire args="$@"con args=("$@")e got=$("$cmd" "$args")con got=$("$cmd" "${args[@]}"). (O semplicemente faregolfscript.rb eseguibile ed ./test ./golfscript.rb chords.gs
eseguilo

4

Python, 160

f='A#BC D EF G3453543'.find
try:
 while 1:x,y,z=sorted(map(lambda x:f(x[0])+f(x[1:])+1,raw_input().split()));print'MMianjoorrr'[f(`y-x`+`z-y`)/14:-1:2]
except:0
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.