내가 방금 뭐 했어? 기타 핑거링을 코드로 번역


22

관련 : 음악 :이 화음에는 무엇이 있습니까? , Tablature 에 대한 메모 , 기타 탭 생성? , 숫자 쌍을 기타 노트로 번역

기타 핑거링이 주어지면 그것이 나타내는 코드를 출력합니다. 표준 입력 및 출력을 사용하거나 문자열을 반환하는 함수를 작성할 수 있습니다.

입력 핑거링은 다음 코드 중 하나로 분류 할 수 있으며 다음과 같이 표현됩니다 (근음이 C 인 경우).

  • 주요 트라이어드 : C
  • 작은 트라이어드 : Cm
  • (주) 일곱째 : C7
  • 미성년자 일곱째 : Cm7

화음이 거꾸로 될 수 있으므로 가장 낮은 음을 근음으로 사용할 수 없습니다. 또한 현실 세계에서 이것이 쉽고 일반적인 핑거링에 의존 할 수도 없습니다. 보다 일반적으로 프로그램의 출력은 피치의 옥타브를 무시하고 동일한 음표 (예 :)에 해당하는 모든 피치를 A동일하게 취급해야합니다.

이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다.

입력 형식

입력은 표준 튜닝 (EADGBE) 에서 6 줄 기타의 각 줄에 대해 해당 줄이 연주되는 프렛을 나타내는 일련의 6 개의 값입니다 . 또한 현이 전혀 연주되지 않음을 나타낼 수도 있습니다. "제로"프렛은 개방 위치라고도하며 프렛 번호는 거기에서 계산됩니다. 기타에 프렛 위치가 21 개라고 가정하면 가장 높은 프렛 위치는 20 번입니다.

예를 들어, 입력 X 3 2 0 1 0은 손가락을 기타 목 상단의 다음 위치에 배치하는 것을 의미합니다.

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

두 번째 줄부터 여섯 번째 줄까지 골라냅니다. 이 ASCII 탭에 해당합니다 .

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

원하는 종류의 입력을 선택할 때 약간의 유연성이 있습니다. 각 프렛 위치는 문자열 또는 숫자로 표현할 수 있습니다. 연주되지 않는 기타 줄은 일반적으로로 표시 X되지만 -1숫자를 사용하는 경우 와 같이 더 쉬운 경우 다른 센티넬 값을 선택할 수 있습니다 . 일련의 6 개 프렛 위치는 목록, 배열 또는 시퀀스 유형, 공백으로 구분 된 단일 문자열 또는 표준 입력으로 다시 입력 할 수 있습니다.

위에서 언급 한 4 가지 코드 형식 중 하나에 해당하는 입력에 의존 할 수 있습니다.

솔루션에 어떤 형태의 입력이 필요한지 게시물에 설명하십시오.

출력 형식

운지법이 적용되는 코드를 설명하는 문자열을 표준 출력으로 반환하거나 인쇄해야합니다. 이 줄은 서로 연결된 두 부분으로 구성됩니다. 총액 사항. 후행 공백이 허용됩니다.

첫 번째 부분은 표시 근음 중 하나를 A, A#/ Bb, B, C, C#/ Db, D, D#/ Eb, E, F, F#/ Gb, G또는 G#/ Ab. (내가 사용하고 #대신 하고, b대신 유니 코드를 필요로하는 피하기 위해.) 그들없이 표현되어야 날카로운 또는 평면없이 표현 될 수있는 루트 메모를 (절대 출력 B#, Fb또는 Dbb); 단일의 날카 롭거나 평평한 기호로 표현할 수없는 것 (즉, C#또는 Db, 그러나 절대로 B##). 즉, 노트 이름에서 우연한 수 (날카 롭거나 평평한) 수를 최소화해야합니다.

두 번째 부분은 메이저 트라이어드, m마이너 트라이어드, 7지배적 인 일곱 번째 또는 m7마이너 일곱 번째에 대해 비어있는 코드 유형을 나타냅니다 . 따라서 G 메이저는 단순히로 출력 G되는 반면 D♯ 마이너 7은 D#m7또는 로 출력 될 수 있습니다 Ebm7. 테스트 사례에서 더 많은 예제를 찾을 수 있습니다.

이론 및 힌트

뮤지컬 악보

반음계는 옥타브 당 12 개의 피치를가집니다. 같은 기질로 조율 될 때, 이들 피치 각각은 그 이웃들 ( 1) 로부터 동등하게 떨어져있다 . 12 반음 (옥타브) 간격의 피치 는 동일한 음표로 간주됩니다. 이는 우리가 0에서 11까지의 정수 모듈로 12와 같은 음표를 취급 할 수 있음을 의미합니다.이 중 7 는 A에서 G까지의 문자 이름으로 2 를 부여 합니다. 12 개의 피치를 모두 명명하기에는 충분하지 않지만 실수로 추가하면 다음과 같이 수정됩니다. 날카롭게) 음표에 반음이 높아지고 flat (평평)을 추가하면 반음이 낮아집니다.

화음

화음은 함께 연주되는 2 개 이상의 음표입니다. 코드 유형은 음표 간의 관계에 따라 달라지며 음표 간의 거리에 따라 결정됩니다. 앞에서 언급했듯이 코드에는 근음이 있습니다. 이 예제에서는 근음을 0으로 취급하지만, 이것은 임의적이며,이 문제에서 중요한 것은 모듈로 산술에서 음 사이의 거리입니다. 해답을 위해 항상 3 가지 코드 또는 7 번째 코드 중 하나의 고유 한 코드 형식이 있습니다. 근음이 항상 최저 주파수 피치는 아닙니다. 다음 4 가지 코드 형식 중 하나로 코드를 설명 할 수 있도록 근음을 선택하십시오.

  • 메이저 3 화음은 음표와 화음입니다 0 4 7.
  • 사소한 화음은 음표와 화음입니다 0 3 7.
  • 지배적 (또는 주 / 부) 일곱 번째 코드는 노트가 있습니다 0 4 7 10.
  • 작은 (또는 미성년자 / 마이너) 일곱 번째의 화음 노트가 있습니다 0 3 7 10.

기타 튜닝

6 현 기타의 표준 조율은 가장 낮은 현에서 E로 시작하여 5, 5, 5, 4 및 5 반음 간격으로 음을칩니다. 가장 낮은 E를 0으로 사용한다는 것은 기타의 모든 현을 묶는 것은 숫자 0 5 10 15 19 24로 된 음높이 , 모듈로 12와 같은 0 5 10 3 7 0음표를 E A D G B E줍니다.

작동 예

입력 값 0 2 2 0 0 0이 음인 경우 음표에 해당 E B E G B E하므로 E, B 및 G 만 해당됩니다.이 음표 Em는 근음으로 E로 번호를 매기면 알 수 있습니다 0 3 7. (결과에 대해 동일한 것이 X 2 X 0 X 0거나 12 14 14 12 12 12).

입력 값이 4 4 6 4 6 4이면 근음 C♯로 번호를 매기 7 0 7 10 4 7면 또는 0 4 7 10이므로 답은 C#7(또는 Db7)입니다. 대신 4 4 6 4 5 4에 번호를 매기면 7 0 7 10 3 7, 또는 0 3 7 10, 즉 C#m7(또는 Dbm7)가됩니다.

테스트 사례

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

2 또는 solfège 에서 do, re, mi 와 같은 이름 입니다. 이 도전에서는 문자 이름을 사용하십시오.

3 이것은 또한 근음의 다른 선택과 함께 주요 여섯 번째 화음이라고 할 수 있습니다. 이 도전에서는 그것을 작은 일곱 번째 이름으로 부르십시오.


3
큰 도전!
루이스 멘도

1
내 미래의 도전에서 속임수로
빠져 나가고 싶은 유혹을 느낀다

출력 문자열에 후행 공백이 허용됩니까?
Luis Mendo

@LuisMendo 확실히; 괜찮아.
Dan Getz

1
@officialaimm 아니오, 다른 상황을 처리 할 필요가 없습니다. 항상 4 가지 코드 형식 중 하나라고 가정 할 수 있습니다. 다시 말해, 코드가 다른 코드를 받으면 원하는대로 (오류를 포함하거나 잘못된 답변을 제공) 할 수 있습니다.
Dan Getz

답변:


9

MATL , 115 114 바이트

[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

입력 형식은입니다 [N 3 2 0 1 0]. 여기서 N사용되지 않는 문자열을 나타냅니다.

출력 문자열은 항상 #아닌을 사용합니다 b.

온라인으로 사용해보십시오! 또는 온라인 컴파일러 시간이 초과되지 않도록 두 부분으로 모든 테스트 사례를 확인하십시오.

설명

[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

4

MS-DOS .COM 파일 (179 바이트)

파일 (여기서는 HEX로 표시됨) :

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

입력은 명령 행을 통해 제공됩니다. 잘못된 입력은 잘못된 프로그램 동작으로 이어질 것입니다!

어셈블러 코드는 다음과 같습니다.

.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

테스트 사례 :

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

나는 이미 두 명의 피아노 연주자가 피아노에서 "네 손으로"연주하는 것을 보았다.

이 테스트 케이스는 내가 기타 연주자에 대해 읽은 첫 번째 사례입니다!

오른손으로 두 드리더라도 이와 같은 코드를 연주 할 수 없습니다!


흠, 오징어가 그 화음을 연주 할 수 있을까? 나는 이것이 "하드"테스트 사례가 될 수 있도록 무작위 검색으로 찾은 것 중 하나라고 생각합니다.
Dan Getz

3

루비, 129 바이트

이전 버전이지만 단일 루프를 사용하며 삼항 연산자를 사용하여 구문 분석 단계와 출력 단계 사이의 순서를 정합니다. 이 작업을 수행하기 위해 약간의 수정이 필요했습니다.

->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])}}

루비, 136 바이트

Llamda 함수는 6 개의 숫자 배열을 인수로 받아 들여 stdout에 출력합니다. 사용하지 않는 문자열은 잘못된 값으로 표시됩니다 (루비의 유일한 잘못된 값은 nil및) 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}}

설명

나는 5원을 기준으로 12 피치의 표현을 사용합니다 . 이는 각 피치 다음에 시퀀스를 제공하는 7 반음 높음 (또는 5 반음 낮음)의 음높이를 의미합니다 F C G D A E B F# C# G# D# A#. 여기에는 두 가지 장점이 있습니다. 하나는 모든 샤프가 함께 나타나는 것입니다. 다른 하나는 5 현베이스의 오픈 스트링 음이 함께 나타나는 것입니다. GDAEB (기타는 관련되어 있지만 약간 더 복잡합니다. 아래 참조).

첫 번째 루프는 6 번 실행됩니다. 표현식 6--~j%5(동등하게 6-(j+1)%5)은 열린 문자열에 대한 메모 값을 제공합니다 E=5 A=4 D=3 G=2 B=6 E=5. 여기에 프렛 수에 7을 곱한 값을 추가합니다 (위에서 볼 수 있듯이 하나의 반음을 추가하면 시퀀스에서 7 자리 앞으로 이동합니다.) 그런 다음 모듈로 12 전체를 가져와 존재하는 음표의 비트 맵을 만듭니다 (우리는 4097<<note value2 연속 옥타브를주는 데 사용 합니다.)

비트 맵을 구성한 후 코드를 검색하여 출력 할 수 있습니다.

다음 사항에 관심이 있습니다.

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

코드 F를 확인하면서 시작하여 루트와 5가 있는지 테스트합니다 : 비트 0과 1 (가장 중요하지 않은 것으로 계산 : 1과 2의 비트) 6 번째 코드를 거부하려면 6 번째 코드도 확인해야합니다. 비트 3 (8 비트)이 없으므로 확인 r&&11==3하고 코드를 인쇄합니다.

우리는 메이저 세 번째를 무시하고 코드 형식을 해결하기 위해 비트 9 (최소 3)와 비트 10 (최소 7)에 전적으로 의존합니다. 이 표현 r>>9&3은 배열에서 올바른 코드 형식을 선택하는 데 사용됩니다.

루프의 끝에서 비트 r/=2코드를 한 비트 오른쪽으로 이동 하여 가능한 코드 근을 순서대로 테스트합니다 F C G D A E B F# C# G# D# A#.

테스트 프로그램에서 언 골프

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

2

자바 스크립트 (ES6), (335) 333 바이트

이 도전과 PPCG SE를 사랑하십시오! 이것은 나의 첫번째 골프이다-나는 그것이 많이 향상 될 수 있다고 확신하기 때문에 제안을 환영한다. (카운트에 f =를 포함 시키면 2 바이트가 떨어졌습니다)

함수 f는 숫자와 'X'를 나타내는 문자열 배열을 취하고와 같은 f(['X','3','2','0','1','0'])코드 (자연 또는 샤프)를 반환합니다 E#m7. 명확성을 위해 줄 바꿈이 추가되었습니다 (바이트 수에 포함되지 않음)

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]

사용 예 :

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

테스트 케이스를 실행하려면 다음을 수행하십시오.

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))}`)
})

설명이 포함 된 언 골프 버전 :

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 */
}

1
사이트에 오신 것을 환영합니다! 나는 당신이 그것을 즐길 기쁘다. :) 불행히도, 나는 JS를
모르므로
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.