얼마나 많은 반음


21

지침

태스크

문자열 또는 목록 / 배열로 입력 된 두 개의 음표가 주어지면, 음표 자체를 포함하여 얼마나 많은 반음이 떨어져 있는지 계산하여 숫자로 출력합니다.

반음 설명 :

반음은 키보드의 한 단계 위 또는 아래입니다. 예를 들면 C에서 C #입니다. 아래에서 볼 수 있듯이 C는 흰색 메모에 있고 C #은 그 위에있는 검은 메모입니다. 반음은 다음을 제외하고 검은 색 음표에서 다음 흰색 음표로 위 또는 아래로 도약합니다.

  • B에서 C로
  • C에서 B로
  • E에서 F로
  • F에서 E로

건반

'A, C' -> 4

'G, G#' -> 2

'F#, B' -> 6

'Bb, Bb' -> 13


규칙

  • 두 음 사이의 가장 큰 거리는 13 반음입니다.
  • 두 번째 입력 된 메모는 항상 첫 번째 입력 된 메모 위에 있습니다.
  • 문자열 또는 배열 / 목록으로 입력을받을 수 있습니다. 당신이 문자열로 촬영하면 노트가 될 것입니다 쉼표로 구분 (예를 들어 String -> 'A, F', Array -> ['A', 'F']).
  • 항상 두 개의 유효한 메모가 제공 될 것이라고 가정 할 수 있습니다.
  • 샤프는로 표시 #되고 플랫은로 표시됩니다b
  • 귀하의 코드는 조화로운 등가물을 지원해야합니다 (예 : F # 및 Gb 모두 지원해야 함)
  • 코드는 이름이 지정된 메모를 지원할 필요는 없지만 예리하거나 평평하지 않은 이름을 지정할 수 있습니다 (예 : E # 또는 Cb를 지원할 필요가 없음). 코드에서 지원하는 경우 보너스 포인트.
  • 코드에서 이중 샤프 또는 이중 플랫을 지원할 필요는 없습니다.
  • 동일한 음 또는 동일한 피치 (예 : 'Gb, Gb'또는 'A #, Bb')를 모두 얻는 경우 두 번째가 첫 번째보다 정확히 한 옥타브가 아니라고 가정 할 수 있습니다.
  • 이것은 코드 골프이므로 최소 바이트 수의 답이 이깁니다.

나는 2를 얻는다 G -> G#둘 다 포함되어 있기 때문에 .
HyperNeutrino

@HyperNeutrino 네 죄송합니다. 나의 실수
Amorris

1
우리는 다음과 같은 메모를 제공해야합니까? Cb또는E# 합니까? 이중 샤프 / 플랫은 어떻습니까?
Sok

1
@Sok 아니요, 코드에서 E # 또는 Cb와 같은 메모를 지원할 필요가 없으며 이중 샤프 또는 플랫을 지원할 필요가 없습니다. 더 명확하게하기 위해 질문을 업데이트했습니다. 혼란을 드려 죄송합니다.
Amorris

2
음악 이론 감지 거리에서 반음 단위로 말할 때 명확하게 말하면 , 시작하는 음표 포함 되지 않습니다 . 수학에서 그것은 (X, Y]C에서 C #이 1 반음이고 C에서 C가 12 반음이되도록 표현되었다 .
Dom

답변:



7

자바 스크립트 (ES6), 78 바이트

@Neil 덕분에 1 바이트 절약

카레 구문에서 메모를합니다 (a)(b) .

a=>b=>((g=n=>'0x'+'_46280ab_91735'[parseInt(n+3,36)*2%37%14])(b)-g(a)+23)%12+2

테스트 사례

해시 기능

해시 함수의 목적은 16 진수로 저장된 반음 오프셋 (C = 0, C # = 1, ..., B = 11)을 포함하는 조회 테이블에서 메모를 포인터로 변환하는 것입니다.

먼저 노트에 '3' 을 추가하고 base-36의 결과 문자열을 구문 분석하여 정수 N을 얻습니다 . '#' 때문에 잘못된 문자, 그것은 간단하게 다음과 같은 모든 문자와 함께 무시됩니다.

그런 다음 계산합니다.

H(N) = ((N * 2) MOD 37) MOD 14

아래는 결과 요약입니다.

 note | +'3' | parsed as | base 36->10 |   *2  | %37 | %14 | offset
------+------+-----------+-------------+-------+-----+-----+--------
  C   |  C3  |    c3     |         435 |   870 |  19 |   5 |  0x0
  C#  |  C#3 |    c      |          12 |    24 |  24 |  10 |  0x1
  Db  |  Db3 |    db3    |       17247 | 34494 |  10 |  10 |  0x1
  D   |  D3  |    d3     |         471 |   942 |  17 |   3 |  0x2
  D#  |  D#3 |    d      |          13 |    26 |  26 |  12 |  0x3
  Eb  |  Eb3 |    eb3    |       18543 | 37086 |  12 |  12 |  0x3
  E   |  E3  |    e3     |         507 |  1014 |  15 |   1 |  0x4
  F   |  F3  |    f3     |         543 |  1086 |  13 |  13 |  0x5
  F#  |  F#3 |    f      |          15 |    30 |  30 |   2 |  0x6
  Gb  |  Gb3 |    gb3    |       21135 | 42270 |  16 |   2 |  0x6
  G   |  G3  |    g3     |         579 |  1158 |  11 |  11 |  0x7
  G#  |  G#3 |    g      |          16 |    32 |  32 |   4 |  0x8
  Ab  |  Ab3 |    ab3    |       13359 | 26718 |   4 |   4 |  0x8
  A   |  A3  |    a3     |         363 |   726 |  23 |   9 |  0x9
  A#  |  A#3 |    a      |          10 |    20 |  20 |   6 |  0xa
  Bb  |  Bb3 |    bb3    |       14655 | 29310 |   6 |   6 |  0xa
  B   |  B3  |    b3     |         399 |   798 |  21 |   7 |  0xb

평지와 샤프 정보

다음은이 해시 함수가 '#' 뒤에 오는 노트가 다음 노트와 'b' 와 동일한 결과를 제공 한다는 것을 증명합니다 . 이 단락에서는 기본 36 수량에 접두사 @ 를 사용합니다 .

예를 들어 Db@ db3 으로 변환 되고 C #@c 로 변환됩니다 (이전 단락 참조). 우리는 그것을 증명하고 싶습니다 :

H(@db3) = H(@c)

또는 일반적인 경우 Y = X + 1 인 경우 :

H(@Yb3) = H(@X)

@ b3 은 10 진수 로 399 입니다. 따라서:

H(@Yb3) =
@Yb3 * 2 % 37 % 14 =
(@Y * 36 * 36 + 399) * 2 % 37 % 14 =
((@X + 1) * 36 * 36 + 399) * 2 % 37 % 14 =
(@X * 1296 + 1695) * 2 % 37 % 14

12961 모듈로 37 에 적합하므로 다음과 같이 단순화 할 수 있습니다.

(@X + 1695) * 2 % 37 % 14 =
((@X * 2 % 37 % 14) + (1695 * 2 % 37 % 14)) % 37 % 14 =
((@X * 2 % 37) + 23) % 37 % 14 =
((@X * 2 % 37) + 37 - 14) % 37 % 14 =
@X * 2 % 37 % 14 =
H(@X)

특별한 경우의 전환이다 G 번호Ab의 우리 예상대로, 헤모글로빈을 상기 식을 준수하기 위해. 그러나 이것은 또한 다음과 같은 이유로 작동합니다.

@ab3 * 2 % 37 % 14 = @hb3 * 2 % 37 % 14 = 4

@ 닐 감사합니다! 최적화는 내 것보다 많은 바이트를 절약합니다.
Arnauld 2019

허, 나는 실제로 나의 배치 솔루션과 반대를 발견했다 ...
Neil

@Neil Batch의 모듈로 부호가 제수의 부호이기 때문에 추측합니다.
Arnauld

아니, 그것은 JS에서와 같이 배당금의 표시이지만, 이전 골프로 인해 반전 된 결과의 부호를 수정하는 것은 약간 골퍼였습니다.
Neil

4

펄, 39 32 바이트

포함 +1을 위해p

STDIN에서 시작 및 종료 메모를 두 줄로 제공

(echo "A"; echo "C") | perl -pe '$\=(/#/-/b/-$\+5/3*ord)%12+$.}{'; echo

코드 만 :

$\=(/#/-/b/-$\+5/3*ord)%12+$.}{


@wastl 그래서 나는 들었다. 나는 메타되는 포스트하지만 :-) 내가 거기 가서 동의하지 않을 수 있습니다 알고 싶습니다
톤 Hospel에게

내 의견은 링크입니다. 부담없이 클릭하십시오.
wastl

이것은 내 것과 매우 유사하게 작동합니다. 그러나 Perl의 경우는 매우 짧습니다. +1
Level River St

@LevelRiverSt 아니라,이 입니다 톤 Hospel은.
msh210

4

apt , 27 바이트

®¬x!b"C#D EF G A"ÃrnJ uC +2

온라인으로 테스트하십시오! 입력을 두 문자열의 배열로 가져옵니다.

또한 모든 기본 음표에서 임의의 양의 샤프 또는 플랫에 사용할 수 있습니다!

설명

®¬x!b"C#D EF G A"ÃrnJ uC +2   Let's call the two semitones X and Y.
®                Ã            Map X and Y by
 ¬                              splitting each into characters,
  x                             then taking the sum of
   !b"C#D EF G A"               the 0-based index in this string of each char.
                                C -> 0, D -> 2, E -> 4, F -> 5, G -> 7, A -> 9.
                                # -> 1, adding 1 for each sharp in the note.
                                b -> -1, subtracting 1 for each flat in the note.
                                B also -> -1, which happens to be equivalent to 11 mod 12.
                                The sum will be -2 for Bb, 2 for D, 6 for F#, etc.
                              Now we have a list of the positions of the X and Y.
                  rnJ         Reduce this list with reversed subtraction, starting at -1.
                              This gets the difference Y - (X - (-1)), or (Y - X) - 1.
                      uC      Find the result modulo 12. This is 0 if the notes are 1
                              semitone apart, 11 if they're a full octave apart.
                         +2   Add 2 to the result.

2

펄 5 + -p, 66 바이트

s/,/)+0x/;y/B-G/013568/;s/#/+1/g;s/b/-1/g;$_=eval"(-(0x$_-1)%12+2"

온라인으로 사용해보십시오!

쉼표로 구분 된 값을 사용합니다. Cb, B #, E #, Fb 및 다중 # / b에도 작동합니다.

설명:

# input example: 'G,G#'
s/,/)+0x/; # replace separator with )+0x (0x for hex) => 'G)+0xG#'
y/B-G/013568/; # replace keys with numbers (A stays hex 10) => '8)+0x8#'
s/#/+1/g; s/b/-1/g; # replace accidentals with +1/-1 => '8)+0x8+1'
$_ = eval # evaluate => 2
    "(-(0x$_-1)%12+2" # add some math => '(-(0x8)+0x8+1-1)%12+2'

eval에 대한 설명 :

(
    - (0x8) # subtract the first key => -8
    + 0x8 + 1 # add the second key => 1
    - 1 # subtract 1 => 0
) % 12 # mod 12 => 0
+ 2 # add 2 => 2
# I can't use % 12 + 1 because 12 (octave) % 12 + 1 = 1, which is not allowed

2

루비 , 56 바이트

->a{a.map!{|s|s.ord*5/3-s[-1].ord/32}
13-(a[0]-a[1])%12}

온라인으로 사용해보십시오!

문자는 5/3다음과 같이 ASCII 코드 시간에 따라 구문 분석 됩니다 (이렇게하면 필요한 반음 수에 오프셋 108을 더함).

A    B    C    D    E    F    G
108  110  111  113  115  116  118

마지막 문자 ( #, b또는 다음과 같이 다시 편지) (32)에 의해 나눈 ASCII 코드로 해석됩니다

# letter (natural) b 
1  { --- 2 --- }   3

이것은 문자 코드에서 뺍니다.

그런 다음 최종 결과는 13-(difference in semitones)%12


2

Stax , 25 24 바이트

╝─°U┤ƒXz☺=≡eA╕δ┴╬\¿☺zt┼§

온라인으로 실행 및 디버깅

동일한 프로그램의 해당 ASCII 표현은 이렇습니다.

{h9%H_H32/-c4>-c9>-mrE-v12%^^

효과적으로, 그것은 공식을 사용하여 각 음의 키보드 색인을 계산 한 다음 결과 간격을 계산합니다.

  1. 베이스 노트에서 시작, A = 2, B = 4, ... G = 14
  2. 우발적 인 오프셋을 계산하십시오 2 - code / 32.code 마지막 문자의 아스키 코드입니다.
  3. 함께 추가하십시오.
  4. 결과가 4보다 크면 1을 빼서 B #을 제거하십시오.
  5. 결과가 7보다 크면 1을 빼고 E #을 제거하십시오.
  6. 결과적으로 생성 된 두 개의 노트 인덱스를 모듈 식으로 빼고 1을 더합니다.

1
["F#","B"]
Weijun Zhou

1
감사. 나는 다른 절반을 조정하지 않고 계산의 절반을 변경했습니다. 고정되어 있습니다.
재귀

1

배치, 136135 바이트

@set/ac=0,d=2,e=4,f=5,g=7,a=9,r=24
@call:c %2
:c
@set s=%1
@set s=%s:b=-1%
@set/ar=%s:#=+1%-r
@if not "%2"=="" cmd/cset/a13-r%%12

설명 : c서브 루틴의 대체 #가 메모 이름에서 +1및로 b바뀝니다 -1. 대소 문자를 구분하지 않으므로이 Bb됩니다 -1-1. 따라서 C...에 대한 변수 A는 대소 문자를 구분하지 않으므로 적절한 반음 수가되도록 선택됩니다 B=-1. 그런 다음 결과 문자열을 평가하고 값에서 결과를 빼는 @xnor의 트릭은 음표 값을 서로 빼는 원하는 효과를 제공합니다. 편집 : 마지막으로 13에서 모듈로를 빼는 @Arnauld의 트릭을 사용하여 원하는 답을 얻고 1 바이트를 절약합니다.



1

젤리 , 28 바이트

O64_ṠH$2¦ḅ-AḤ’d5ḅ4µ€IḞṃ12FṪ‘

두 개의 문자 목록을 허용하고 정수를 리턴하는 모나드 링크.

온라인으로 사용해보십시오! 또는 가능한 모든 사례를 참조하십시오.

방법?

입력 문자의 서수에 대한 기괴한 산술을 수행하여 음을 0에서 12까지의 정수에 매핑 한 다음 12로 모듈로에 대한 프록시로 기본 압축 해제를 수행합니다.

O64_ṠH$2¦ḅ-AḤ’d5ḅ4µ€IḞṃ12FṪ‘ - Main link, list of lists    e.g. [['F','#'],['B']]  ...or [['A','b'],['G','#']]
                  µ€         - for €ach note list          e.g.  ['F','#'] ['B']          ['A','b'] ['G','#']
O                            - { cast to ordinal (vectorises)    [70,35]   [66]           [65,98]   [71,35]
 64                          -   literal 64
   _                         -   subtract (vectorises)           [-6,29]   [-2]           [-1,-34]  [-7,29]
        ¦                    -   sparse application...
       2                     -   ...to indices: [2] (just index 2)
      $                      -   ...do: last two links as a monad:
    Ṡ                        -          sign                     [-6,1]    [-2]           [-1,-1]   [-7,1]
     H                       -          halve                    [-6,-0.5] [-2]           [-1,-0.5] [-7,0.5]
         ḅ-                  -   convert from base -1            5.5       -2             0.5       7.5
           A                 -   absolute value                  5.5       2              0.5       7.5
            Ḥ                -   double                          11.0      4              1.0       15.0
             ’               -   decrement                       10.0      3              0.0       14.0
              d5             -   divmod by 5                     [2.0,2.0] [0,3]          [0.0,0.0] [2.0,4.0]
                ḅ4           -   convert from base 4             10.0      3              0.0       12.0
                             - } -->                             [10.0,3]                 [0.0,12.0]
                    I        - incremental differences           [-7.0]                   [12.0]
                     Ḟ       - floor (vectorises)                [-7]                     [12]
                      ṃ12    - base decompress using [1-12]      [[5]]                    [[1,12]]
                         F   - flatten                           [5]                      [1,12]
                          Ṫ  - tail                              5                        12
                           ‘ - increment                         6                        13

또한 28 바이트에서 ...

xnor의 Python 2 답변의 ( 직접적이지 않은) 포트 ...

O×5:3z60_Ṡ¥2¦60U1¦Fḅ-‘N%12+2

가능한 모든 경우를 시도하십시오


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.