Klavierakkorde auf weißen Tasten

9

Hintergrundgeschichte [was nicht stimmt]

Ein Klavier ist wie folgt aufgebaut:

! [http://www.piano-lessons-made-simple.com/images/2-Octave-Labled.gif

Bei meinem Klavier sind jedoch alle schwarzen Tasten defekt!

Ich möchte trotzdem einige Akkorde auf meinem kaputten Klavier spielen können.

In der Musik ist ein Akkord eine Gruppe von Noten, die zusammen gespielt werden. Um die Eingabe von Akkorden zu ermöglichen, werde ich zunächst definieren, was ein Halbton ist.

Was ist ein Halbton?

Ein Halbton ist die kleinste Entfernung in der westlichen Musik. Wenn Sie sich den oberen Teil des Klaviers ansehen, sehen Sie, dass Sie normalerweise von einer schwarzen zu einer weißen Taste wechseln können oder umgekehrt. Zwischen Bund Cund Eund Fgibt es jedoch keinen schwarzen Schlüssel.

Was ist ein Akkord?

Für diese Herausforderung definieren wir einen Akkord als eine Reihe von Noten mit einer bestimmten Anzahl von Halbtönen dazwischen. Nehmen wir zum Beispiel eine Aufnahme eines 4-3-3Akkords ab C(für Musiker ist dies ein V 7- Akkord in F-Dur). Wir fangen an bei C. Wir zählen bis 4 Halbtonschritte: C#, D, D#, E. Die nächste Note ist E, und wir zählen 3 Halbtonschritten nach oben danach: F, F#, G. Die nächste Note ist G, und wir zählen 3 Halbtonschritten nach oben danach: G#, A, Bb. Also bekommen wir C-E-G-Bb. Yay! Aber warte ... Bbist ein schwarzer Schlüssel und die sind kaputt ... Wenn wir jedoch anfangen G, bekommen wir G-B-D-F! Yay!

Eingang

Die Eingabe erfolgt als Liste von Ganzzahlen in einem beliebigen vernünftigen Format. Dies stellt den oben beschriebenen Akkord dar.

Ausgabe

Die Ausgabe sollte eine Liste von Notizen sein, für die ich anfangen kann, nur weiße Tasten zu verwenden. Dies kann auch nur eine Zeichenfolge aller bis zu 7 Noten sein, da alle Schlüsselnamen aus einem Zeichen bestehen. Sie müssen auch mit einer leeren Ausgabe umgehen können.

Testfälle

input -> output // comments
4 3 -> C F G // this is a major triad
3 4 -> D E A // this is a minor triad
4 3 3 -> G // this is the major-minor seventh chord
3 3 3 -> [empty output] // this is the diminished-diminished seventh chord. All of them use black keys
4 4 -> [empty output] // this is an augmented triad
3 3 -> B // this is a diminished triad
1 -> B E // this is just a minor second
11 -> C F // this is just a major seventh

Andere Spezifikationen

  • Standardschlupflöcher verboten
  • Sie können davon ausgehen, dass die Eingabe mindestens eine Ganzzahl hat
  • Sie können davon ausgehen, dass alle Ganzzahlen nicht negativ und kleiner als 12 sind (da das Klavier alle 12 Noten wiederholt).
  • Die Ausgabe kann in beliebiger Reihenfolge erfolgen

Gewinnkriterien

Die kürzeste gültige Einreichung ab dem 15. April wird akzeptiert.

HyperNeutrino
quelle
Wir können "nicht negativ und kleiner als 12" annehmen - sollte das nicht "positiv und kleiner oder gleich 12" sein?
Jonathan Allan
@ JonathanAllan Grundsätzlich gibt es keinen Unterschied; Meine Methode erlaubt eine perfekte Unisono, aber keine perfekte Oktave. deins umgekehrt. Theoretisch mag Ihre Einschränkung sinnvoller sein, aber ich denke, ich sollte sie wahrscheinlich nicht ändern, da es bereits Antworten gibt und die Herausforderung dadurch nicht grundlegend geändert wird.
HyperNeutrino

Antworten:

3

Gelee , 25 Bytes

236ḃ2ṙЀ7+\€Ṭ
+\ịþ¢Ạ€TịØA

Probieren Sie es online aus! oder sehen Sie sich eine Testsuite an

Wie?

236ḃ2ṙЀ7+\€Ṭ - Link 1, white-note-offsets: no arguments
236ḃ2         - 236 in bijective base 2 [2, 2, 1, 2, 2, 1, 2] - semitones G->A, A->B ...
     ṙЀ7     - rotate left by, mapped over [1,2,3,4,5,6,7] - i.e. as above for each
                    starting white key (1st one A->B,B->C,...; 2nd B->C,C->D,...; etc)
         +\€  - reduce €ach with addition - i.e. absolute number of semitones: [[2,3,5,7,8,10,12],[1,3,5,6,8,10,12],[2,4,5,7,9,11,12],[2,3,5,7,9,10,12],[1,3,5,7,8,10,12],[2,4,6,7,9,11,12],[2,4,5,7,9,10,12]]
            Ṭ - untruth (vectorises) - make lists with 1s at those indexes: [[0,1,1,0,1,0,1,1,0,1,0,1],[1,0,1,0,1,1,0,1,0,1,0,1],[0,1,0,1,1,0,1,0,1,0,1,1],[0,1,1,0,1,0,1,0,1,1,0,1],[1,0,1,0,1,0,1,1,0,1,0,1],[0,1,0,1,0,1,1,0,1,0,1,1],[0,1,0,1,1,0,1,0,1,1,0,1]]

+\ịþ¢Ạ€TịØA - Main link: list of semitone gap integers (even negatives will work)
+\          - reduce by addition - gets the absolute semitone offsets needed
    ¢       - last link (1) as a nilad
   þ        - outer product with:
  ị         -     index into - 7 lists, each with 1s for white and 0s for black keys hit
                      note that indexing is modular and all the lists are length 12
                      so any integer is a valid absolute offset, not just 0-11 inclusive
     Ạ€     - all truthy for €ach - for each get a 1 if all keys are white ones, else 0
       T    - truthy indexes - get the valid starting white keys as numbers from 1 to 7
        ị   - index into:
         ØA -     the uppercase alphabet
Jonathan Allan
quelle
6

MATL , 31 Bytes

Vielen Dank an Jonathan Allan für die Korrektur.

'BAGFEDC'"GYs12X\110BQX@YSYsm?@

Probieren Sie es online aus! Oder überprüfen Sie alle Testfälle .

Erläuterung

Das Muster 2 2 1 2 2 2 1gibt die Intervalle zwischen aufeinanderfolgenden weißen Tasten an. Das Programm verwendet eine Schleife, die alle zyklischen Verschiebungen auf dieses Grundmuster anwendet, um jede Taste als potenziell tiefste Note des Eingangsakkords zu testen. Für jede Verschiebung wird die kumulative Summe des Musters erhalten. Zum Beispiel wurde Bdas Muster als potenziell niedrigste Note verschoben 1 2 2 1 2 2 2und seine kumulative Summe ist 1 3 5 6 8 10 12.

Um zu sehen, ob dies einen 4 3 3Akkord unterstützen kann, berechnen wir die kumulative Summe der Akkordintervalle 4 7 10. reduzieren Sie es über 1-basiertes Modulo 12 (ein Intervall von 14würde geben 2); und prüfen Sie, ob diese Zahlen alle Mitglieder der zulässigen Werte sind 1 3 5 6 8 10 12. Dies ist in diesem Beispiel nicht der Fall. Wäre dies der Fall gewesen, würden wir den Brief ausgeben B.

Die Entsprechung zwischen zyklischen Verschiebungen und Ausgabebuchstaben wird durch die Zeichenfolge definiert 'BAGFEDC'. Dies zeigt an, dass 'B'(erstes Zeichen) einer zyklischen Verschiebung um entspricht 1; 'A'(zweites Zeichen) entspricht einer zyklischen Verschiebung um 2etc.

'BAGFEDC'  % Push this string
"          % For each character from the string
  G        %   Push input array
  Ys       %   Cumulative sum
  12X\     %   1-based modulo 12, element-wise (1,12,13,14 respectively give 1,12,1,2)
  110BQ    %   Push 110, convert to binary, add 1 element-wise: gives [2 2 1 2 2 2 1]
  X@       %   Push current iteration index, starting at 1
  YS       %   Cyclic shift to the right by that amount
  Ys       %   Cumulative sum
  m        %   Ismember. Gives an array of true of false entries
  ?        %   If all true
    @      %     Push current character
           %   End (implicit)
           % End (implicit)
           % Display (implicit)
Luis Mendo
quelle
5

Mathematica, 110 Byte (ISO 8859-1-Codierung)

±i_:=#&@@@Select["A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#&/@(Accumulate[i~Prepend~#]&/@Range@12),FreeQ@"#"]

Definiert eine unäre Funktion, ±die eine Liste von Ganzzahlen als Eingabe verwendet (eigentlich keine Einschränkungen hinsichtlich der Größe oder der Vorzeichen der Ganzzahlen) und gibt eine Liste von Zeichenfolgen mit einem Zeichen zurück. Gibt zum Beispiel ±{3,4}zurück {"A","D","E"}.

"A#BC#D#EF#G#"~StringTake~{Mod[#,12,1]}&/@#ist eine Funktion, die eine Liste von Ganzzahlen in die entsprechenden Notennamen umwandelt, außer dass sie #für eine beliebige schwarze Taste steht. Dies wird auf jedes Element von angewendet Accumulate[i~Prepend~#]&/@Range@12, das eine Liste von Notenwerten aus der Listeneingabeliste der Notenintervalle erstellt, beginnend mit jeder möglichen Note von 1 bis 12. Wir filtern alle diese Notennamenlisten heraus, die "#"using enthalten Select[...,FreeQ@"#"], und dann Geben Sie die erste Note in jeder verbleibenden Liste mit zurück #&@@@.

Greg Martin
quelle
Schöne Einreichung!
HyperNeutrino
Frage: Verwendet Mathematica ein eigenes Bytesystem? Dies sind 110 Zeichen, aber in UTF-8 sind es aufgrund des +/-Symbols 111 Bytes .
HyperNeutrino
Sie können die Zuweisung vollständig entfernen und eine Funktion einfach "implizit zurückgeben".
wizzwizz4
@ wizzwizz4: Ich habe festgestellt, dass ich die Variable benennen muss, Accumulate[i~Prepend~#]&da es sonst zu einem Curry-Konflikt kommen würde. Fühlen Sie sich frei, eine Problemumgehung zu finden!
Greg Martin
@HyperNeutrino: Sie haben Recht, dass UTF-8 die Standardcodierung ist, aber Mathematica kann (normalerweise) auch in der ISO 8859-1-Codierung funktionieren. Ich habe das in der Post notiert.
Greg Martin
3

Python 2, 159 155 Bytes

(Veröffentlichen Sie dies, nachdem Sie sichergestellt haben, dass es eine gültige Einreichung gibt, die kürzer als diese ist.)

import numpy
s='C.D.EF.G.A.B'
def k(y):return lambda x:s[(x+y)%12]
for i in range(12):
    if s[i]!='.'and'.'not in map(k(i),numpy.cumsum(input())):print s[i]

So ziemlich nur die triviale Lösung. Eingaben als Liste von Ganzzahlen und Ausgaben mit jedem Zeichen in einer einzelnen Zeile.

-4 Bytes durch Entfernen einer unnötigen Variablen

HyperNeutrino
quelle
3

JavaScript (ES6), 72 71 68 Byte

a=>[..."C1D1EF1G1A1B"].filter((c,i,b)=>!+c>a.some(e=>+b[i+=e,i%12]))

Durchläuft jede Taste, wobei schwarze Tasten weggelassen werden, und überprüft dann, ob die kumulierte Summe der Halbtöne niemals auf einer schwarzen Taste landet.

Bearbeiten: 3 Bytes dank @Arnauld gespeichert.

Neil
quelle
4
Lesbarkeit?! Sind Sie sicher, dass Sie auf der richtigen Seite sind? :-)
wizzwizz4