튜닝 문자열


9

직무

주어진 주파수로 튜닝되고 주어진 지점에서 눌려진 문자열에 대해 소리가 나지 않는 센트 수와 함께 소리를내는 프로그램을 작성하십시오.

간단하게하기 위해, 생성 된 사운드의 주파수와 그것이 눌려지는 오른쪽의 줄 길이는 반비례한다고 가정합니다.

참고 :이 작업은 기본 톤만 다루고 오버톤 / 기타 고조파는 다루지 않습니다.

입력

프로그램에는 두 가지 데이터가 제공됩니다.

  • 해당 문자열을 나타내는 임의의 길이의 문자열입니다. 이 문자열은 X를 표시하여 문자열을 누른다.

    [-----] is a string divided in six sections (five divisions).
    [--X--] is a string pressed at the exact center of the string.
    [X----] is a string pressed at 1/6 the length of the string. (Length used is 5/6)
    [-X--] is a string pressed at 2/5 of the length of the string. (Length used is 3/5)
    

    오른쪽의 문자열 부분을 사용하여 음이 들린다 고 가정합니다 X.

  • 문자열이 튜닝되는 빈도를 나타내는 숫자 (정수일 필요는 없음). 이 숫자의 정밀도는 소수점 이하 최대 4 자리입니다.

이는 주파수 사이에 존재할 것이다 전달된다고 가정 될 수있다 10 Hz와 40000 Hz.

입력은 원하는 형식으로 전달 될 수 있습니다. 답변에서 프로그램에 입력이 허용되는 방식을 지정하십시오.

산출

프로그램은 12 톤 균등 한 튜닝 시스템에서 가장 가까운 음표 *와 문자열로 표시된 소리가 가장 가까운 음에서 가장 가까운 음의 수를 출력해야합니다 (가장 가까운 센트로 반올림).

+n센트는 n노트 위 -n/ 아래의 센트, 노트 / 플랫 아래의 센트 를 나타내는 데 사용해야합니다 .

노트는 과학적인 피치 표기법으로 출력되어야합니다. A4가로 조정되었다고 가정합니다 440Hz. 평평하고 선명한 음표에는 b 및 #을 사용하십시오. 참고 : 날카 로우거나 평평하게 사용할 수 있습니다. 의 메모에 466.16Hz대해 A#또는 메모에 Bb대해 출력 될 수 있습니다.

출력에 이전에 지정된 두 개의 정보 만 포함되어있는 한 출력 형식은 사용자에게 달려 있습니다 (즉, 가능한 모든 단일 출력을 인쇄하는 것은 허용되지 않음).

* 가장 가까운 음표는 센트 수로 측정 된 입력에 의해 표시되는 소리에 가장 가까운 음표를 의미합니다 (따라서 음표 내에있는 음표 50 cents). 소리가 50 cents반올림 후 두 개의 다른 음표에서 멀어지면 두 음표 중 하나가 출력 될 수 있습니다.

예

프로그램은 다음 예제뿐만 아니라 모든 경우에 작동해야합니다.

Output             Input Frequency   Input String
A4,  +0  cents     220               [-----X-----]
A5,  +0  cents     220               [--------X--]
D5,  -2  cents     440               [--X--------]
B4,  -49 cents     440               [X----------]
A#4, +19 cents*    314.1592          [X-]
Eb9, +8  cents*    400               [-----------------------X]
Eb11,+8  cents*    100               [--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]
D#1, +49 cents*    10                [--X]
A0,  -11 cents     11.7103           [---X--]

* 날카 롭거나 평평하게 출력 될 수 있습니다.

잠재적으로 유용한 링크

이것은 가장 짧은 답변이 이깁니다.


나는 당신의 예제가 다소 일관성이 없다고 생각합니다 : 첫 번째 [--X--]문자열 에 따르면 이 논리 x를 따르면 마지막 문자열은 [-X--]3/8 (2/5 아님)에있을 것입니다. 아니면 내가 잘못 이해하고 있습니까?
— flawr

마지막 줄에 @flawr [-X--], 문자열은 4 곳 (따라서 5 부분)으로 나뉘어지고 두 번째 부분에서 눌려집니다. 따라서을 눌렀으며 2/5사용 된 길이는 3/5입니다.
— es1024

아 알았어 이제 알다시피, 각각 -기본적으로 부서의 위치를 ​​나타냅니다. 설명해 주셔서 감사합니다!
— flawr

답변:


1

BBC 기본, 161 #

  REM get frequency and string. Store length of string in n for later.
  INPUT f,s$
  n=LEN(s$)

  REM store floating-point value of note in semitones above (C0-0.5). Store integer value in n% (offset effectively means it will be rounded not truncated.)
  n=LN(f*(n-1)/(n-INSTR(s$,"X"))/15.8861)/LN(2)*12
  n%=n

  REM format printing to whole numbers only
  @%=2^17

  REM Output note name and octave. Output cents (discrepancy between n and n%, minus the offset of 0.5)
  PRINT MID$("C C#D D#E F F#G G#A A#B ",n%MOD12*2+1,2);INT(n/12)'(n-0.5-n%)*100'

점수는 댓글을 제외합니다. 아직 골프를 치지 않았습니다.

산출

두 개의 긴 경우를 제외한 모든 테스트 사례에서 올바르게 수행됩니다. 들어 Eb9그것을 테스트 케이스에서 누락 된 하나의 대시가 보인다 (22)이있다 -하나 X(24 개)와 동일한 조각으로 문자열을 분할. 내 수동 계산에 따르면, 이것은 9600Hz이며 D9보다 37 센트 높습니다. 이것이 바로 내 프로그램이 출력하는 것입니다. 다른 대시를 추가하면 Eb9 + 8 센트가 표시됩니다. 불행히도 BBC Basic은 255자를 초과하는 문자열을 처리 할 수 ​​없으므로 Eb11오류가 발생합니다.

여기에 이미지 설명을 입력하십시오


3

C, 179

main(n,d){float f;scanf("%*[^X]%nX%*[-]%n]%f",&n,&d,&f);f=log(f*d/(d-n))*17.3123-57.376;n=d=f+.5;n=n%12*7+784;printf("%c%d%c,%+2.0f cents\n",n/12,(d+9)/12,n%12/7*3+32,(f-d)*100);}

아스키 사진을 한 줄로, 별도의 줄로 주파수를받습니다.

매직 넘버 17.3123와 의 정확도를 줄이면 몇 개의 문자를 삭제할 수 있습니다 57.376.

골프가 없으면 프로그램은 다음과 같습니다.

main(n,d)
{
    float f; // 'float' and '%f' better than 'double' and '%lf'

    scanf("%*[^X]%nX%*[-]%n]%f", &n, &d, &f);
    // n is the number of chars before 'X'
    // d is the number of chars before ']'
    // f is the frequency

    // Calculate the tuned frequency
    f = f * d / (d - n);

    // Convert the frequency to logarithmic scale, relative to pitch A0
    f=log(f)*17.3123-57.376;
    // alternatively: f = log2(f / (440 / 16)) * 12;

    // Round to nearest integer
    n=d=f+.5;

    // Calculate the note name ('A', 'B', etc), multipled by 12 for convenience
    n=n%12*7+784;

    printf("%c%d%c,%+2.0f cents\n", // output example: B4 ,-49 cents
        n/12,        // note name
        (d+9)/12,    // octave number
        n%12/7*3+32, // if n%12 is large enough, it's '#' else ' ' (natural)
        (f-d)*100);  // number of cents; stdio rounds it to integer
}

2
멋진 scanf형식 문자열의 경우 +1 당신이 할 수있을 줄 몰랐어요 나중에 당신에게 출력 코드를 확인합니다 (I는 C와 비슷한 출력을 위해 나에게 발생하지만, 내가 경쟁적으로 모든 일을 할 수있는 방법을 볼 수없는이 일에 대해 생각했다.) 나는 가정 d+9당신이 색인하고 있기 때문에입니다 음표 A는 옥타브 수를 음표 C의 색인으로 조정해야합니다.
— Level River St

그렇습니다. +9는 옥타브가 C에서 시작한다는 사실을 보상합니다. 음표 이름 계산과 비슷하거나 비슷합니다. 참고 이름의 경우 순환 시프트는 LUT에 의해 구현 될 수 있지만 더 계산적인 수학적 방법을 선호합니다.
— anatolyg

1

자바 스크립트 (199)

예를 들어 t('[X-]',314.1592)

t=(s,f)=>{l=s.length-1;p='C C# D D# E F F# G G# A B H'.split(' ');n=12*Math.log2(f*l/(l-s.indexOf('X'))/16.3515978);m=n+.5|0;return p[m%12]+(n/12|0)+' '+((n-m)*100+.5|0)}

결정된. (유럽에 살고 있으므로 Bb 대신 B를 사용하고 B = 대신 H를 사용했습니다.)


Flawr, 당신은 독일 사람입니까? 나는 항상 B와 H를 유럽식 표기법이 아닌 독일 식 표기법으로 생각했습니다. 영국과 아일랜드는 Bb와 B를 사용합니다. 스페인과 이탈리아는 SIb와 SI를 사용합니다 (DO RE MI FA SOL LA SI와 동일). 어쨌든 그것은 하나의 문자를 절약하는 것입니다.
— Level River St

예, 저는 독일어를 사용하는 국가입니다. 다른 유럽 국가에서는 Doremi 시스템을 사용한다는 사실을 알지 못했습니다 (사람들이 어린이 교육에 사용한다고 들었습니다). 어쨌든 그것은 단지 1 문자를 절약하고 실제로 요구 사항을 충족시키지 못한다고 말한 이후로 농담이었습니다. =)
— flawr

센트 수가 음수이면 t('[---X--]',11.7103)( 예 : (마지막 예) -10대신에 센트 수를 잘못 반올림합니다.-11
— es1024

를 사용 p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)하면 추가로 2자를 절약 할 수 있습니다.
— Sean Latham

@ es1024 아, 알고 있어야합니다 : round(x) = x+.5|0양수에 대해서만 올바른 둥근 함수를 구현했기 때문에 나중에 수정하겠습니다. @ipi 감사합니다!
— flawr

1

파이썬 3 : 175

import math
def t(b,s):l=len(s)-1;n=12*math.log2(b*l/(l-s.index("X"))/16.35);m=round(n);return"%s%s%+d"%(("C C# D D# E F F# G G# A A# B".split()*99)[m],m//12,round(100*(n-m)))

언 골프 드 :

import math

c0 = 16.35

def tuning (base_frequency, string):
    return formatted (note_number (frequency (base_frequency, string)))

def formatted (note_number):
    return "{name}{octave:d}{cents:+d}".format (name=note_name (note_number),
                             octave=octave (note_number),
                             cents=cents_out (note_number))

def note_name (note_number):
    return ("C C# D D# E F F# G G# A A# B".split() * 99)[round (note_number)]

def note_number (frequency):
    return 12 * math.log2 (frequency / c0)

def octave (note_number):
    return round (note_number) // 12

def cents_out (note_number):
    return round (100 * (note_number - round (note_number)))

def frequency (base_frequency, string):
    string_length = len (string) - 1
    held_length = string_length - string.index ("X")
    return base_frequency * string_length / held_length

if "__main__" == __name__:

    print ("Testing functions against known values...")
    assert "A4+0"     == tuning (220,      "[-----X-----]")
    assert "A5+0"     == tuning (220,      "[--------X--]")
    assert "D5-2"     == tuning (440,      "[--X--------]")
    assert "B4-49"    == tuning (440,      "[X----------]")
    assert "A#4+19"   == tuning (314.1592, "[X-]")
    assert "D#9+8"    == tuning (400,      "[-----------------------X]")
    assert "D#11+8"   == tuning (100,      "[--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------X]")
    assert "D#1+49"   == tuning (10,       "[--X]")
    assert "A0-11"    == tuning (11.7103,  "[---X--]")
    print ("Tests passed.")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.