Was habe ich gerade gespielt? Übersetzen Sie Gitarrengriffe in Akkorde

22

Siehe auch: Musik: Was ist in diesem Akkord? , Hinweise zur Tabulatur , Gitarren-Tabs generieren? , Zahlenpaare in Gitarrennoten übersetzen

Geben Sie bei gegebenem Gitarrengriff den Akkord aus, den er repräsentiert. Sie können die Standardeingabe und -ausgabe verwenden oder eine Funktion schreiben, die eine Zeichenfolge zurückgibt.

Die eingegebenen Fingersätze können als einer der folgenden Akkorde klassifiziert werden, die wie folgt ausgedrückt werden (wenn der Grundton C wäre):

  • Haupttriade: C
  • Moll-Triade: Cm
  • (dominante) siebte: C7
  • Moll 7 .: Cm7

Der Akkord ist möglicherweise invertiert, sodass Sie sich nicht darauf verlassen können, dass die unterste Note der Grundton ist. Sie können sich auch nicht darauf verlassen, dass dies in der realen Welt ein einfacher oder üblicher Fingersatz ist. Im Allgemeinen muss die Ausgabe Ihres Programms die Oktaven der Tonhöhen ignorieren und alle Tonhöhen, die derselben Musiknote (dh derselben Note A) entsprechen, als gleich behandeln.

Das ist , also gewinnt der kürzeste Code in Bytes.

Eingabeformat

Die Eingabe ist eine Reihe von 6 Werten, die für jede Saite einer 6-saitigen Gitarre in der Standardstimmung (EADGBE) angeben, an welchem ​​Bund diese Saite gespielt wird. Dies könnte auch darauf hinweisen, dass die Saite überhaupt nicht gespielt wird. Der "nullte" Bund ist auch als die offene Position bekannt, und die Bundnummern zählen von dort aufwärts. Angenommen, die Gitarre hat 21 Bundpositionen, so dass die höchste Bundposition die Nummer 20 ist.

Zum Beispiel X 3 2 0 1 0bedeutet die Eingabe , dass Sie Ihre Finger an den folgenden Stellen am oberen Rand des Gitarrenhalses platzieren:

(6th) |---|---|---|---|---
      |-X-|---|---|---|---
      |---|---|---|---|---
      |---|-X-|---|---|---
      |---|---|-X-|---|---
(1st) |---|---|---|---|---

und Klimpern der 2. bis 6. Saite. Es entspricht dieser ASCII-Registerkarte :

e |-0-|
B |-1-|
G |-0-|
D |-2-|
A |-3-|
E |---|

Sie können die Art der Eingabe flexibel auswählen: Jede Bundposition kann als Zeichenfolge oder als Zahl ausgedrückt werden. Gitarrensaiten, die nicht gespielt werden, werden normalerweise mit einem gekennzeichnet X. Sie können jedoch einen anderen Sentinel-Wert auswählen, wenn dies für Sie einfacher ist (z. B. -1wenn Sie Zahlen verwenden). Die Reihe von 6 Bundpositionen kann als Liste, Array oder Sequenztyp, als einzelne durch Leerzeichen getrennte Zeichenfolge oder als Standardeingabe eingegeben werden.

Sie können sich auf den Eingang verlassen, der einem der oben genannten 4 Akkordtypen entspricht.

Bitte erläutern Sie in Ihrem Beitrag, welche Form der Eingabe Ihre Lösung annimmt.

Ausgabeformat

Sie müssen einen String, der den Akkord beschreibt, für den der Fingersatz bestimmt ist, entweder zurückgeben oder zur Standardausgabe drucken. Diese Zeichenfolge besteht aus zwei miteinander verbundenen Teilen. Kapitalisierung Angelegenheiten. Leerzeichen dürfen nachgestellt werden.

Der erste Teil gibt die Grundnote , eines A, A#/ Bb, B, C, C#/ Db, D, D#/ Eb, E, F, F#/ Gb, Goder G#/ Ab. (Ich verwende #statt , und bstatt zu vermeiden Unicode erfordert.) Root stellt fest , dass ohne scharfe oder flach ausgedrückt werden kann , muss ohne sie ausgedrückt werden (nie ausgegeben B#, Fboder Dbb); diejenigen, die nicht ausgedrückt werden können, müssen durch ein einzelnes scharfes oder flaches Symbol ausgedrückt werden (dh entweder C#oder Db, aber niemals B##). Mit anderen Worten, Sie müssen die Anzahl der Vorzeichen (scharfe oder flache Stellen) im Namen der Notiz minimieren.

Der zweite Teil gibt die Art des Akkords an, entweder leer für eine Dur-Triade, mfür eine Moll-Triade, 7für die dominante Septime oder m7für die Moll-Septime. So wird ein G-Dur einfach als ausgegeben G, während ein d-Moll-Septime als entweder D#m7oder ausgegeben werden könnte Ebm7. Weitere Beispiele finden Sie in den Testfällen am Ende.

Theorie & Hinweise

Musiknoten

Die chromatische Skala hat 12 Tonhöhen pro Oktave. Bei gleicher Stimmung ist jede dieser Tonhöhen gleich weit von ihren Nachbarn 1 entfernt . Tonhöhen, die 12 Halbtöne voneinander entfernt sind (eine Oktave), gelten als dieselbe Note. Dies bedeutet, dass wir Noten wie ganze Zahlen modulo 12 von 0 bis 11 behandeln können. Sieben von ihnen werden mit den Buchstaben 2 von A bis G bezeichnet. scharf) zu einer Note macht es einen Halbton höher, und das Hinzufügen eines ♭ (flach) macht es einen Halbton niedriger.

Akkorde

Ein Akkord besteht aus 2 oder mehr gleichzeitig gespielten Noten. Die Art des Akkords hängt von den Beziehungen zwischen den Noten ab, die durch die Abstände zwischen ihnen bestimmt werden können. Ein Akkord hat, wie bereits erwähnt, einen Grundton. In diesen Beispielen wird der Grundton als 0 behandelt, dies ist jedoch willkürlich und alles, was bei dieser Herausforderung wichtig ist, ist der Abstand zwischen den Noten in Modulo-Arithmetik. Es gibt immer einen eindeutigen Akkordtyp für die Antwort, entweder eine Triade oder einen siebten Akkord . Der Grundton ist nicht immer die Tonhöhe mit der niedrigsten Frequenz. Wählen Sie den Grundton so, dass Sie den Akkord als einen der vier folgenden Akkordtypen beschreiben können:

  • Eine Dur-Triade ist ein Akkord mit den Noten 0 4 7.
  • Eine Moll-Triade ist ein Akkord mit den Noten 0 3 7.
  • Ein dominanter (oder Dur / Moll) Septakkord hat die Noten 0 4 7 10.
  • Ein Moll- (oder Moll- / Moll-) Septakkord enthält die Noten 0 3 7 10. 3

Gitarrenstimmung

Standardstimmung auf einer 6-saitigen Gitarre beginnt mit E auf der untersten Saite und trifft dann Noten in Intervallen von 5, 5, 5, 4, dann 5 Halbtönen, die die Saiten hinaufgehen. Wenn Sie das niedrigste E als 0 nehmen, bedeutet dies, dass Sie durch das Anschlagen aller Saiten der Gitarre die Tonhöhen nummerieren 0 5 10 15 19 24, die Modulo 12 entspricht 0 5 10 3 7 0, oder die Noten E A D G B E.

Arbeitsbeispiele

Wenn Ihre Eingabe so ist 0 2 2 0 0 0, entspricht dies den Noten E B E G B E, also nur E, B und G. Diese bilden den Akkord Em, der sichtbar wird, indem Sie sie mit dem Grundton als E nummerieren und uns geben 0 3 7. (Das Ergebnis wäre dasselbe für X 2 X 0 X 0, oder 12 14 14 12 12 12.)

Wenn Ihre Eingabe lautet 4 4 6 4 6 4, nummerieren Sie diese mit einer Wurzel aus C♯ ergibt 7 0 7 10 4 7oder 0 4 7 10, lautet die Antwort C#7(oder Db7). Wenn es stattdessen 4 4 6 4 5 4wäre, würde die Nummerierung geben 7 0 7 10 3 7, oder 0 3 7 10, was ist C#m7(oder Dbm7).

Testfälle

X 3 2 0 1 0  --->  C
0 2 2 0 0 0  --->  Em
X 2 X 0 X 0  --->  Em
4 4 6 4 6 4  --->  C#7  (or Db7)
4 4 6 4 5 4  --->  C#m7 (or Dbm7)
0 2 2 1 0 0  --->  E
0 0 2 2 2 0  --->  A
X X 4 3 2 2  --->  F#   (or Gb)
3 2 0 0 0 1  --->  G7
X X 0 2 1 1  --->  Dm7
3 3 5 5 5 3  --->  C
4 6 6 5 4 4  --->  G#   (or Ab)
2 2 4 4 4 5  --->  B7
0 7 5 5 5 5  --->  Am7
7 6 4 4 X X  --->  B
8 6 1 X 1 3  --->  Cm
8 8 10 10 9 8 -->  Fm
0 19 5 16 8 7 -->  Em
6 20 0 3 11 6 -->  A#   (or Bb)
X 14 9 1 16 X -->  G#m  (or Abm)
12 14 14 12 12 12 --> Em
15 14 12 12 12 15 --> G
20 X 20 20 20 20  --> Cm7
X 13 18 10 11 10  --> A#7 (or Bb7)

1 durch die Logarithmen ihrer Frequenzen

2 oder, in solfège , Namen wie do, re, mi . Verwenden Sie in dieser Herausforderung die Buchstabennamen.

3 Dies könnte auch als Dur-Sechstel-Akkord bezeichnet werden, mit einer anderen Wahl des Grundtons. Nennen Sie es in dieser Herausforderung beim untergeordneten siebten Namen.

Dan Getz
quelle
3
Große Herausforderung!
Luis Mendo
1
Versuchung, als Betrüger von meiner zukünftigen Herausforderung abzuschließen: D (Ich hatte eine sehr ähnliche Herausforderung im Sinn, aber Sie waren sichtlich schneller.)
Fehler
Ist das nachgestellte Leerzeichen in der Ausgabezeichenfolge zulässig?
Luis Mendo
@ LuisMendo sicher; das ist gut.
Dan Getz
1
@officialaimm nein, du musst keine anderen Situationen bewältigen. Sie können davon ausgehen, dass es sich immer um einen dieser 4 Akkordtypen handelt. Mit anderen Worten, Ihr Code kann tun, was Sie wollen (einschließlich Fehler oder falsche Antwort), wenn er einen anderen Akkord erhält.
Dan Getz

Antworten:

9

MATL , 115 114 Bytes

[OAXICO]+tZN~)Y@!"@t1)XH- 12\XzXJK7hm?O.]JI7hm?'m'.]J[KCX]m?'7'.]J[ICX]m?'m7'.]]'FF#GG#AA#BCC#DD#E'l2741B~QY{HX)wh

Das Eingabeformat ist [N 3 2 0 1 0], wo Nnicht verwendete Zeichenfolge angibt.

Die Ausgabezeichenfolge verwendet immer #, nicht b.

Probieren Sie es online! Oder überprüfen Sie alle Testfälle in zwei Teilen, um das Timeout des Online-Compilers zu vermeiden:

Erläuterung

[OAXICO]            % Push [0 5 10 3 7 0]. This represents the pitch of each open
                    % string relative to the lowest string, modulo 12
+                   % Add to implicit input. May contain NaN's, for unused strings
tZN~)               % Remove NaN's
Y@!                 % Matrix of all permutations, each in a column
"                   % For each column
  @                 %   Push current column
  t1)               %   Duplicate and get first entry
  XH                %   Copy into clipboard H
  - 12\             %   Subtract. This amounts to considering that the first note
                    %   of the current permutation is the root, and computing
                    %   all intervals with respect to that
  12\               %   Modulo 12
  Xz                %   Remove zeros
  XJ                %   Copy into clipboard J
  K7hm?             %   Are all intervals 4 or 7? If so: it's a major chord
    O               %     Push 0 (will become space when converted to char)
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  I7hm?             %   Are all intervals 3 or 7? If so: it's a minor chord
    'm'             %     Push this string
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  [KCX]m?           %   Are all intervals 4, 7 or 10? If so: it's a dominant-7th
                    %   chord
    '7'             %     Push this string
    .               %     Break for loop
  ]                 %   End if
  J                 %   Push array of nonzero intervals again
  [ICX]m?           %   Are all intervals 3, 7 or 10? If so: it's a minor 7th chord
    'm7'            %     Push this string
    .               %     Break for loop
  ]                 %   End if
]                   % End for. The loop is always exited via one of the 'break'
                    % statements. When that happens, the stack contains 0, 'm',
                    % '7' or 'm7', indicating the type of chord; and clipboard H
                    % contains a number that tells the root note using the lowest 
                    % string as base (1 is F, 2 is F# etc)
'FF#GG#AA#BCC#DD#E' % Push this string. Will be split into strings of length 1 or 2
l                   % Push 1
2741B~Q             % Push [1 2 1 2 1 2 1 1 2 1 2 1] (obtained as 2741 in binary,
                    % negated, plus 1)
Y{                  % Split string using those lengths. Gives a cell array of
                    % strings: {'F', 'F#', ..., 'E'}
H                   % Push the identified root note
X)                  % Index into cell array of strings
wh                  % Swap and concatenate. Implicitly display
Luis Mendo
quelle
4

MS-DOS-COM-Datei (179 Byte)

Die Datei (hier als HEX angezeigt):

fc be 81 00 bf 72 01 31 db b9 06 00 51 e8 73 00
59 e2 f9 b9 0c 00 be 48 01 ad 39 c3 74 0d 40 75
f8 d1 fb 73 03 80 c7 08 e2 ec c3 31 db 88 cb 8a
87 59 01 e8 42 00 8a 87 65 01 e8 3b 00 81 c6 08
00 ac e8 33 00 ac eb 30 91 00 89 00 91 04 89 04
ff ff 00 00 6d 00 37 00 6d 37 42 41 41 47 47 46
46 45 44 44 43 43 00 23 00 23 00 23 00 00 23 00
23 00 04 09 02 07 0b 04 84 c0 74 06 b4 02 88 c2
cd 21 c3 8a 0d 47 ac 3c 20 76 fb 30 ed 3c 41 73
22 2c 30 72 0b 86 c5 b4 0a f6 e4 00 c5 ac eb ed
88 e8 00 c8 30 e4 b1 0c f6 f1 88 e1 b8 01 00 d3
e0 09 c3

Die Eingabe erfolgt über die Kommandozeile. Ungültige Eingaben führen zu ungültigem Programmverhalten!

Der Assembler-Code sieht folgendermaßen aus:

.text
.code16
ComFileStart:
    cld
    mov $0x81, %si
    mov $(TuneTable-ComFileStart+0x100), %di
    xor %bx, %bx
    # 6 strings: Build the mask of played tones
    mov $6, %cx
NextStringRead:
    push %cx
    call InsertIntoMask
    pop %cx
    loop NextStringRead

    # Check all base tones...
    mov $12, %cx
TestNextTone:
    mov $0x100+ChordTable-ComFileStart, %si
TestNextChord:
    lodsw
    # Is it the chord we are searching for?
    cmp %ax, %bx
    je FoundChord 
    # Is it the end of the table?
    inc %ax
    jnz TestNextChord
    # Transpose the chord we really play
    # and go to the next tone
    # This code rotates the low 12 bits of
    # BX one bit right
    sar $1, %bx
    jnc NoToneRotated
    add $8, %bh
NoToneRotated:
    loop TestNextTone
EndOfProgram:
    ret

FoundChord:
    # Get and print the tone name
    xor %bx, %bx
    mov %cl, %bl
    mov (ToneNamesTable+0x100-1-ComFileStart)(%bx),%al
    call printChar
    mov (ToneNamesTable+0x100+12-1-ComFileStart)(%bx),%al
    call printChar
    # Get the chord name suffix and print it
    add $(ChordNamesTable-ChordTable-2),%si
    lodsb
    call printChar
    lodsb
    # Note: Under MS-DOS 0x0000 is the first word on
    # the stack so the "RET" of printChar will jump
    # to address 0x0000 which contains an "INT $0x21"
    # (end of program) instruction
    jmp printChar

ChordTable:
    # Major, Minor, Major-7, Minor-7
    .word 0x91, 0x89, 0x491, 0x489, 0xFFFF
ChordNamesTable:
    .byte 0,0,'m',0,'7',0,'m','7'
ToneNamesTable:
    .ascii "BAAGGFFEDDCC"
    .byte 0,'#',0,'#',0,'#',0,0,'#',0,'#',0
TuneTable:
    .byte 4,9,2,7,11,4

#
# Subfunction: Print character AL;
#              Do nothing if AL=0
#
printChar:
    test %al, %al
    jz noPrint
    mov $2, %ah
    mov %al, %dl
    int $0x21
noPrint:
    ret

#
# Subfunction: Get one finger position
#              and insert it into a bit mask
#              of tones being played
#
# Input:
#
#   [DS:DI] = 
#        Tuning of current string (0=C, 1=C#, ..., 11=B)
#        Actually only 2=D, 4=E, 7=G, 9=A and 11=B are used
#
#   DS:SI = Next character to read
#
#   DF = Clear
#
# Input and Output:
#
#    BX = Bit mask
#    DI = Will be incremented
#
# Destroys nearly all registers but SI and BX
#
InsertIntoMask:
    mov (%di), %cl
    inc %di
SkipSpaces:
    lodsb
    cmp $' ', %al
    jbe SkipSpaces
# Now evaluate each digit
    xor %ch, %ch
GetNextDigit:
    # Number = 10*Number+Digit
    cmp $'A', %al
    jae DigitIsX
    sub $'0', %al
    jb DigitsDone
    xchg %al, %ch
    mov $10, %ah
    mul %ah
    add %al, %ch
    lodsb
    jmp GetNextDigit
DigitsDone:
    # Add the tune of the string
    # and perform modulus 12
    mov %ch, %al
    add %cl, %al
    xor %ah, %ah
    mov $12, %cl
    div %cl
    mov %ah, %cl
    mov $1, %ax
    shl %cl, %ax
    or %ax, %bx
DigitIsX:
    ret

Testfälle:

6 20 0 3 11 6 -->  A#   (or Bb)

Ich habe schon zwei Klavierspieler gesehen, die zusammen "vierhändig" auf einem Klavier gespielt haben.

Dieser Testfall ist das erste Mal, dass ich etwas über Gitarristen lese, die dies tun!

Selbst wenn Sie mit der rechten Hand tippen, können Sie so eine Schnur nicht spielen!

Martin Rosenau
quelle
Hmm, vielleicht könnte ein Tintenfisch diesen Akkord spielen? Ich denke, das ist einer von denen, die ich durch eine zufällige Suche gefunden habe, so dass es einige "harte" Testfälle geben könnte.
Dan Getz
3

Ruby, 129 Bytes

Wie die Vorgängerversion, jedoch mit einer einzigen Schleife, mit ternärem Operator, um zwischen dem Analyseschritt und dem Ausgabeschritt zu wechseln. Einige andere geringfügige Änderungen waren erforderlich, um diese Arbeit zu machen.

->a{r=0
18.times{|j|j<6?a[j]&&r|=8194<<(6--~j%5+a[j]*7)%12:(r/=2)&11==3&&puts("CGDAEBF"[j%7]+?#*(j/13)+['',?m,?7,'m7'][r>>9&3])}}

Rubin, 136 Bytes

Die Llamda-Funktion akzeptiert ein Array mit 6 Zahlen als Argument und gibt es an stdout aus. Nicht verwendete Zeichenfolge wird durch einen falschen Wert dargestellt (die einzigen falschen Werte in Ruby sind nilund false.)

->a{r=0
6.times{|j|a[j]&&r|=4097<<(6--~j%5+a[j]*7)%12}
12.times{|j|r&11==3&&puts("FCGDAEB"[j%7]+?#*(j/7)+['',?m,?7,'m7'][r>>9&3]);r/=2}}

Erläuterung

Ich benutze eine Darstellung der 12 Tonhöhen basierend auf dem Quintenkreis . Dies bedeutet, dass auf jede Tonhöhe eine um 7 Halbtöne höhere (oder 5 Halbtöne niedrigere) Tonhöhe folgt, die die Sequenz ergibt F C G D A E B F# C# G# D# A#. Dies hat zwei Vorteile. Eines ist, dass alle Schärfen zusammen erscheinen. Das andere ist, dass die offenen Saitennoten des 5-Saiter-Basses zusammen erscheinen: GDAEB (die Gitarre ist verwandt, aber etwas komplexer, siehe unten).

Die erste Schleife läuft 6 mal. Der Ausdruck 6--~j%5(äquivalent 6-(j+1)%5) gibt die Notenwerte für die offenen Saiten: E=5 A=4 D=3 G=2 B=6 E=5. Dazu addieren wir die Bundzahl multipliziert mit 7 (wie oben zu sehen ist, bewegt uns das Hinzufügen eines Halbtons um 7 Stellen in der Sequenz vorwärts.) Dann nehmen wir das Ganze Modulo 12 und machen eine Bitmap der vorhandenen Noten (wir) verwenden 4097<<note value2 aufeinander folgende Oktaven zu geben.)

Nachdem wir die Bitmap erstellt haben, können wir den Akkord suchen und ausgeben.

Wir interessieren uns für folgende Hinweise:

Note       position in      position in             Note      position in 
           semitone domain  circle of fifths                  circle of fifths 
Root       0                0                       Root      0
Minor 3rd  3                9                       Fifth     1
Major 3rd  4                4                       Sixth     3
Fifth      7                1                       Major 3rd 4
Sixth      9                3                       Minor 3rd 9
Minor 7th  10               10                      Minor 7th 10

Beginnen wir mit der Prüfung auf Akkord F und prüfen, ob der Grundton und der fünfte vorhanden sind: die Bits 0 und 1 (von der niedrigsten Stelle ausgehend: die Bits 1 und 2). Um sechste Akkorde abzulehnen, müssen wir auch den sechsten prüfen fehlt: Bit 3 (8er Bit), also überprüfen wir das r&&11==3und drucken den Akkord , wenn ja.

Wir ignorieren die Dur-Terz und verlassen uns vollständig auf Bit 9 (Moll-Terz) und Bit 10 (Moll-7.Th.), um den Akkordtyp zu ermitteln. Der Ausdruck r>>9&3wird verwendet, um den richtigen Akkordtyp aus einem Array auszuwählen.

Am Ende der Schleife, verschieben wir das Bitmap eines Bit nach rechts r/=2den möglichen Akkorde Wurzeln in Sequenz zu testen: F C G D A E B F# C# G# D# A#.

Ungolfed im Testprogramm

f=->a{                            #Accept array of 6 numbers as argument.
  r=0                             #Setup an empty bitmap.

  6.times{|j|                     #For each string
    a[j]&&                        #if the fret value is truthy (not nil or false)
    r|=4097<<(6--~j%5+a[j]*7)%12  #calculate the note value in the circle of fifths and add to the bitmap.
  }

  12.times{|j|                    #For each possible root note
    r&11==3&&                     #if root and fifth are present (bits 0 and 1) and sixth is absent (bit 3) 
    puts("FCGDAEB"[j%7]+?#*(j/7)+ #output the note name and a sharp symbol if necessary, followed by
    ['',?m,?7,'m7'][r>>9&3])      #m and/or 7 as indicate by bits 9 and 10.
    r/=2
  }
}

print 1;f[[nil,3,2,0,1,0]]       #  C
print 2;f[[0,2,2,0,0,0]]         #  Em
print 3;f[[nil,2,nil,0,nil,0]]   #  Em
print 4;f[[4,4,6,4,6,4]]         #  C#7 
print 5;f[[4,4,6,4,5,4]]         #  C#m7 
print 6;f[[0,2,2,1,0,0]]         #  E
print 7;f[[0,0,2,2,2,0]]         #  A
print 8;f[[nil,nil,4,3,2,2]]     #  F#  
print 9;f[[3,2,0,0,0,1]]         #  G7
print 10;f[[nil,nil,0,2,1,1]]    #  Dm7
print 11;f[[3,3,5,5,5,3]]        #  C
print 12;f[[4,6,6,5,4,4]]        #  G#  
print 13;f[[2,2,4,4,4,5]]        #  B7
print 14;f[[0,7,5,5,5,5]]        #  Am7
print 15;f[[7,6,4,4,nil,nil]]    #  B
print 16;f[[8,6,1,nil,1,3]]      #  Cm
print 17;f[[8,8,10,10,9,8]]      #  Fm
print 18;f[[0,19,5,16,8,7]]      #  Em
print 19;f[[6,20,0,3,11,6]]      #  A#  
print 20;f[[nil,14,9,1,16,nil]]  #  G#m 
print 21;f[[12,14,14,12,12,12]]  #  Em
print 22;f[[15,14,12,12,12,15]]  #  G
print 23;f[[20,nil,20,20,20,20]] #  Cm7
print 24;f[[nil,13,18,10,11,10]] #  A#7
Level River St
quelle
2

Javascript (ES6), 335 - 333 Byte

Ich liebe diese Herausforderung und PPCG SE! Dies ist mein erstes Golf - Vorschläge willkommen, da ich sicher bin, dass es viel verbessert werden könnte. (2 Bytes abgeschlagen, da ich f = in die Zählung einbezogen hatte)

Function verwendet feine Reihe von Zeichenfolgen, die Zahlen und 'X' darstellen, f(['X','3','2','0','1','0'])und gibt einen Akkord (natürlich oder scharf) zurück E#m7. Zeilenumbrüche zur Verdeutlichung hinzugefügt (nicht in Byteanzahl enthalten)

f=c=>[s=new Map([[435,''],[345,'m'],[4332,7],[3432,'m7']]),
n=[...new Set(c.map((e,i)=>e?(+e+[0,5,10,3,7,0][i])%12:-1)
.filter(e=>++e).sort((a,b)=>a>b))],d=[...n,n[0]+12].reduce(
(a,c,i)=>i?[...a,(c-n[i-1]+12)%12]:[],0).join``.repeat(2),
m=+d.match(/(34|43)(5|32)/g)[0],'E0F0F#0G0G#0A0A#0B0C0C#0D0D#'
.split(0)[n[d.indexOf(m)]]+s.get(m)][4]

Anwendungsbeispiel:

console.log(f(['0','2','2','0','0','0'])); // Em

So führen Sie Testfälle aus:

tests=`X 3 2 0 1 0 ---> C
0 2 2 0 0 0 ---> Em
X 2 X 0 X 0 ---> Em
4 4 6 4 6 4 ---> C#7 (or Db7)
4 4 6 4 5 4 ---> C#m7 (or Dbm7)`; // and so on...

tests.split`\n`.forEach(e=>{
    console.log(`Test: ${e}
      Result: ${f(e.split(' ').slice(0,6))}`)
})

Ungolfed Version mit Erklärung:

f = (c) => {
    s = new Map([
        [435,''], [345,'m'], [4332,7], [3432,'m7'] 
    ]) /* Each key in s describes the intervals (semitones)
          between consecutive notes in a chord, when it is
          reduced to a single octave, including the interval
          from highest back to lowest. The values describe
          the corresponding chord suffix. E.g. C-E-G has
          intervals C-4-E-3-G-5-C. 435=major=no suffix. */

    n = [ ...new Set(
        c.map( 
         (e,i) => e ? ( +e + [0,5,10,3,7,0][i] )%12 : -1 
         ).filter( (e) => ++e ).sort( (a,b) => a>b )
        ) ] /* take the input array, c, and transform each fret
               position into a note. remove non-notes (-1), sort
               in tone order, remove duplicates. An input of
               positions X 13 18 10 11 10 becomes notes
               (-1) 6 4 1 6 10 then 1 4 6 10. */

    d = [ ...n, n[0] + 12 ].reduce(
        (a,c,i) => i ? [ ...a, (c - n[i-1] + 12)%12 ] : [], 0
    ).join``.repeat(2)
    /* convert the note array, n, into an interval string, d,
       including the lowest note repeated above it to capture
       all intervals. Repeat it twice so that, regardless of the
       inversion played, the intervals will appear in root order
       somewhere. E.g. notes 1-4-6-10 and 13 (1+12)
       become intervals 3 2 4 3, and string for searching
       32433243 */

    m = +d.match( /(34|43)(5|32)/g )[0];
      /* m is the matched chord pattern. In this case, 4332. */

    return 'E0F0F#0G0G#0A0A#0B0C0C#0D0D#'.split(0)[
    n[ d.indexOf(m) ]
    /* get the position in the interval string where the root
       interval first occurs. this corresponds to the position
       of the chord root note in the note array, n. convert this
       number 0-12 to a note name E - D# */
    ] + s.get(m)
       /* add the suffix corresponding to the matched
       chord interval pattern */
}
Chris M
quelle
1
Willkommen auf der Seite! Ich bin froh zu hören, dass es Ihnen gefällt. :) Leider kenne ich kein JS, daher habe ich keine Tipps, aber möglicherweise finden Sie einige hier
DJMcMayhem