Die Major-Minor-Dichotomie

15

In einer Liste mit Akkorden werden sie entweder als "Dur" oder "Moll" bezeichnet.

Eingang

Die Eingabe erfolgt in einer Liste von Akkorden, einer pro Zeile, die aus drei durch ein Leerzeichen getrennten Noten besteht. Jede Note besteht aus dem Namen der Note in Großbuchstaben ( A- G) und einem optionalen Versehen ( #oder b). Akkorde können in beliebiger Umkehrung sein (dh die Noten können in beliebiger Reihenfolge sein).

Ausgabe

Wenn der Akkord Dur ist, geben Sie 'Dur' aus. Wenn der Akkord moll ist, geben Sie 'Minor' aus. Wenn der Akkord weder Dur noch Moll ist, geben Sie eine leere Zeile aus.

Beispiel

Eingang

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

Ausgabe

Major
Minor

Minor
Major
Minor
Major

Testskripte

Wie in einigen meiner früheren Fragen habe ich auch hier einige Testskripte geschlachtet, die ursprünglich von Joey und Ventero erstellt wurden , um einige Testfälle für diese Frage bereitzustellen:

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

Belohnung

Jeder Beitrag, bei dem ich nachprüfen kann, ob er der Spezifikation entspricht, die Tests besteht und offensichtlich einen Golfversuch unternommen hat, wird von mir positiv bewertet (bitte geben Sie Ihre Antwort an). Die kürzeste Lösung bis zum Ende des 13.10.2012 wird als Sieger anerkannt.

Eine kleine Theorie

Für diejenigen unter Ihnen, die keine Kenntnisse der Musiktheorie haben, sind hier genügend Informationen, damit Sie am Wettbewerb teilnehmen können.

Ein Dur- oder Moll-Akkord besteht aus drei Noten, die durch ein bestimmtes Halbtonmuster voneinander getrennt sind. Wenn wir den Grundton des Akkords als 0 betrachten, ist ein Dur-Akkord das Muster 0-4-7 und ein Moll-Akkord das Muster 0-3-7. Die Sache wird durch die Tatsache, dass einige Noten einen Halbton voneinander entfernt sind und andere einen Ton voneinander entfernt. Die Verteilung der Halbtöne von Ab- G#ist wie folgt:

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#/Abbedeutet, dass dies G#die gleiche Note ist wie Ab. Daraus können wir ersehen, dass der Akkord Ab C Ebein Dur-Akkord ist, und das Ab Cb Ebist Moll.

Erschwerend weiter zählt, der Akkord Eb Cb Abgilt das gleiche wie zu sein Ab Cb Eb, Cb Eb Abund Cb Ab Ebund so weiter. Jede dieser Variationen ist immer noch ein Mollakkord.

Gareth
quelle
2
Ich denke, Ihr Bash-Tester benötigt Eingaben und erwartete Antworten ausgetauscht.
Flodel
@flodel Ja, du hast recht. Tut mir leid, ich habe es jetzt korrigiert. Ich muss überprüfen, ob das Powershell-Testskript auch nicht dasselbe Problem hat.
Gareth

Antworten:

3

GolfScript, 83 Zeichen

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

'>2%}%

Dies ist eine schnelle erste Lösung. Ich bin sicher, dass dies weiter Golf spielen kann. Besteht die Bash-Testsuite, nachdem der Fehler behoben wurde, auf den Flodel in den Kommentaren hingewiesen hat.

Edit 1: 5 Zeichen mit einer kürzeren Methode gespeichert, um die kanonisierten Dur- und Moll-Akkordmuster zu erkennen.

Edit 2: 2 weitere Zeichen mit kompakterer Ausgabecodierung gespeichert, inspiriert von der Lösung von grc. (Danke!) Als Nebeneffekt druckt der Code jetzt nach der Ausgabe eine zusätzliche Leerzeile, aber das Testkabel scheint das zu akzeptieren, also denke ich, dass es in Ordnung ist. :)

So funktioniert das:

  • Die äußere Schleife n%{ }%n*teilt die Eingabe nur in Zeilen auf, führt den Code innerhalb der geschweiften Klammern für jede Zeile aus und verbindet die Ergebnisse mit neuen Zeilen.

  • ' '%Teilt jede Zeile in ein Array von Noten. 1\{'A#BC D EF G'?+}/Konvertiert dann für jede dieser Noten diese Note in eine Halbtonzahl, indem nach jedem ihrer Zeichen in der Zeichenfolge gesucht 'A#BC D EF G'und die Positionen addiert werden (dies ist -1 für jedes Zeichen, das in der Zeichenfolge nicht gefunden wird, insbesondere einschließlich b). (Ich bin mir sicher, dass ich diesen Trick schon einmal gesehen habe.) Zum Schluss .dupliziert man jede Zahl, so dass am Ende der Schleife zB die Eingabe F Ab Cin umgewandelt wurde [9 9 0 0 4 4].

  • Wir sortieren dann die Noten mit $, verschieben die erste Note mit an das Ende (+und teilen das Array in Paare mit auf 2/, so dass es nun zB so aussieht [[9 0] [0 4] [4 9]]. Dann {~- 12%}%bildet jedes Paar von Notizen in seine Differenz modulo 12, in unserem Beispiel Array drehen [9 8 7].

  • Anschließend .(+wird eine Kopie des Arrays erstellt und die Elemente werden um eine Position nach links gedreht. Wir machen das zweimal und sammeln die Kopien in einem Array mit ], so dass unser Beispiel nun so aussieht [[9 8 7] [8 7 9] [7 9 8]].

  • Wir sortieren dann dieses Array von Arrays mit $und nehmen das erste Element - in diesem Fall [7 9 8]- mit 0=. Wir machen dann eine Kopie dieses Arrays ( .), sortieren es ( $), sammeln sowohl das unsortierte als auch das unsortierte Array in einem anderen Array von Arrays ( ]) und suchen nach dem ersten Vorkommen des Arrays [7 8 9](das geschrieben wurde 10,7>, um zwei Zeichen zu sparen) ) drin.

  • Dies gibt uns entweder 0(wenn das unsortierte Array war [7 8 9]und somit der Akkord Dur ist), 1(wenn das unsortierte Array eine Permutation von war [7 8 9], die, vorausgesetzt, dass ihr erstes Element [7 9 8]klein sein muss, nur sein kann, den Akkord moll zu machen) oder -1(wenn auch das sortierte Array nicht gleich ist [7 8 9]).

  • Diese Zahl wird dann als Startindex für den String verwendet "MMaijnoorr\n\n"(wobei die \ns als tatsächliche Zeilenvorschübe im Code angegeben sind), von dem wir das Zeichen und jede zweite nachfolgende als Ausgabe nehmen. Wenn der Index -1 ist, beginnen wir mit dem letzten Zeichen des Strings, der nur ein Zeilenvorschub ist.

Ilmari Karonen
quelle
Gute Erklärung. Ich habe die gleichen Schwierigkeiten, die ich immer mit GolfScript zu haben scheine - ich kann es zeilenweise aufrufen, um es zu testen, echo "G# B# Eb" | ruby golfscript.rb ilmari.gsaber wie führe ich das Testskript darauf aus? Ich habe es versucht, ./test ruby golfscript.rb ilmari.gsaber es gab nichts davon. (Ich habe dir bereits eine +1 gegeben, weil es offensichtlich funktioniert, aber ich bin nur neugierig)
Gareth
1
@Gareth: Sieht so aus, als wäre das ein Fehler im Bash-Testskript - es werden nicht alle Argumente richtig behandelt. Um dies zu beheben, ersetzen Sie args="$@"mit args=("$@")und got=$("$cmd" "$args")mit got=$("$cmd" "${args[@]}"). (Oder einfach golfscript.rbausführbar machen und ausführen als ./test ./golfscript.rb chords.gs.)
Ilmari Karonen
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
grc
quelle