Dây điều chỉnh


9

Bài tập

Viết chương trình xác định nốt nhạc phát ra, cùng với bao nhiêu xu ngoài giai điệu, của một chuỗi được điều chỉnh theo tần số cho trước và nhấn xuống tại một điểm nhất định.

Để đơn giản, giả sử rằng tần số của âm thanh được tạo ra và độ dài của chuỗi ở bên phải nơi nó được nhấn là tỷ lệ nghịch.

Lưu ý: tác vụ này chỉ xử lý ở giai điệu cơ bản, chứ không phải với âm bội / hài âm khác.

Đầu vào

Chương trình của bạn được cung cấp hai phần dữ liệu:

  • Một chuỗi có độ dài tùy ý, đại diện cho chuỗi trong câu hỏi. Chuỗi này sẽ được đánh dấu bằng X trong đó chuỗi được giữ.

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

    Giả sử ghi chú được phát ra bằng cách sử dụng một phần của chuỗi ở bên phải của X.

  • Một số (không nhất thiết phải là số nguyên), biểu thị tần số mà chuỗi được điều chỉnh. Độ chính xác của số này sẽ có nhiều nhất là bốn chữ số qua số thập phân.

Có thể giả định rằng tần số được truyền sẽ nằm giữa 10 Hz40000 Hz.

Đầu vào có thể được thông qua trong một định dạng của sự lựa chọn của bạn. Vui lòng xác định cách nhập liệu được chấp nhận vào chương trình của bạn trong câu trả lời của bạn.

Đầu ra

Chương trình của bạn phải xuất cả ghi chú gần nhất * trong hệ thống điều chỉnh tính khí bằng nhau mười hai âm và số xu cách xa nốt gần nhất mà âm thanh được biểu thị bởi chuỗi sẽ là (làm tròn đến cent gần nhất).

+nxu nên được sử dụng để biểu thị nxu sắc nét / trên ghi chú và -nxu cho căn hộ / bên dưới ghi chú.

Các ghi chú nên được xuất ra trong ký hiệu cao độ khoa học. Giả sử A4 được điều chỉnh đến 440Hz. Sử dụng b và # cho ghi chú phẳng / sắc nét. Lưu ý: Có thể sử dụng sắc nét hoặc phẳng. Đối với ghi chú tại 466.16Hz, A#hoặc Bbcó thể được xuất ra cho ghi chú.

Định dạng đầu ra là tùy thuộc vào bạn, miễn là đầu ra chỉ chứa hai mẩu thông tin được chỉ định trước đó (nghĩa là in mọi đầu ra có thể không được phép).

* ghi chú gần nhất đề cập đến ghi chú gần nhất với âm thanh được biểu thị bằng đầu vào, được đo bằng số xu (do đó, ghi chú nằm trong 50 centsâm thanh). Nếu âm thanh 50 centscách xa hai nốt khác nhau (sau khi làm tròn), thì một trong hai nốt có thể được xuất ra.

Ví dụ

Chương trình của bạn nên hoạt động cho tất cả các trường hợp, không chỉ các ví dụ sau.

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

* Hoặc sắc hoặc phẳng có thể đã được xuất ra.

Liên kết hữu ích tiềm năng

Đây là nên câu trả lời ngắn nhất sẽ thắng.


Tôi nghĩ rằng các ví dụ của bạn có phần không nhất quán: Theo [--X--]chuỗi đầu tiên , chuỗi được nhấn ở giữa bộ phận xđược đặt, trong khi chuỗi cuối cùng [-X--]sẽ ở 3/8 (không phải 2/5) khi tuân theo logic này. Hay tôi hiểu điều gì sai?
flawr

@flawr cho phần cuối cùng, [-X--]chuỗi được chia ở 4 vị trí (và do đó thành 5 phần) và được nhấn ở phần thứ hai của các phần này. Vì vậy, nó được nhấn tại 2/5, và chiều dài được sử dụng là 3/5.
es1024

Ah ok bây giờ tôi thấy, vì vậy mỗi -cơ bản đại diện cho vị trí của các bộ phận, cảm ơn bạn đã giải thích!
flawr

Câu trả lời:


1

BBC cơ bản, 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'

Điểm không bao gồm ý kiến. Chưa chơi golf.

Đầu ra

Thực hiện chính xác trên tất cả các trường hợp thử nghiệm ngoại trừ hai trường hợp dài. Vì Eb9dường như có một dấu gạch ngang bị thiếu trong trường hợp thử nghiệm: Có 22 -và một X, chia chuỗi thành 24 phần bằng nhau. Theo tính toán thủ công của tôi, đây là 9600Hz, cao hơn 37 cent so với D9. Đây chính xác là những gì chương trình của tôi đưa ra. Nếu tôi thêm một dấu gạch ngang khác, tôi nhận được Eb9 + 8 xu. Thật không may, BBC Basic không thể xử lý các chuỗi trên 255 ký tự, vì vậy Eb11trường hợp này có lỗi.

nhập mô tả hình ảnh ở đây


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

Tự nhận hình ảnh ascii trên một dòng và tần số trên một dòng riêng biệt.

Một vài ký tự có thể được loại bỏ bằng cách giảm độ chính xác của các số ma thuật 17.312357.376.

Không có golf, chương trình trông như thế này:

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
+1 cho scanfchuỗi định dạng tuyệt vời . Tôi không có ý tưởng bạn có thể làm điều đó. Tôi sẽ kiểm tra bạn mã đầu ra sau (Tôi nghĩ về việc này trong C và mặc dù một cái gì đó tương tự xảy ra với tôi cho đầu ra, tôi không thể nhìn thấy một cách để làm toàn bộ điều cả cạnh tranh.) Tôi giả định d+9là bởi vì bạn đang lập chỉ mục trên lưu ý A để bạn phải điều chỉnh số quãng tám thành chỉ số trên ghi chú C: Tôi tự hỏi liệu có cách nào khác không.
Cấp sông St

Có, +9 bù cho thực tế là quãng tám bắt đầu tại C. Đó là hoặc thực hiện một sửa chữa tương tự như cách tính tên ghi chú. Đối với tên ghi chú, sự dịch chuyển vòng tròn có thể được thực hiện bằng LUT, nhưng tôi thích cách tính toán "toán học" hơn.
anatolyg

1

JavaScript (199)

Gọi nó như là 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)}

Đã sửa. (Vì tôi sống ở châu Âu nên tôi đã sử dụng B thay vì Bb và H thay vì B =)


Flawr, bạn là người Đức phải không? Tôi luôn nghĩ B và H là một ký hiệu của Đức, không phải là một ký hiệu châu Âu. Vương quốc Anh và Ireland sử dụng Bb và B. Tây Ban Nha và Ý sử dụng SIb và SI (như trong DO RE MI FA SOL LA SI.). Dù sao, nó chỉ là tiết kiệm của một nhân vật.
Cấp sông St

Có, tôi là một quốc gia nói tiếng Đức, tôi không biết rằng các quốc gia châu Âu khác sử dụng hệ thống Doremi đó (tôi chỉ nghe người ta sử dụng nó trong giáo dục trẻ em). Dù sao nó cũng chỉ là một trò đùa vì như bạn nói nó chỉ tiết kiệm được 1 char và không thực sự đáp ứng yêu cầu =)
flawr

Điều này dường như làm tròn số xu không chính xác nếu số xu là âm (ví dụ: t('[---X--]',11.7103)(ví dụ cuối cùng) đưa ra -10thay vì-11
es1024

Sử dụng p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)giúp bạn tiết kiệm thêm 2 ký tự.
Sean Latham

@ es1024 Ồ tôi nên biết: Đó là vì tôi đã triển khai hàm tròn round(x) = x+.5|0mà chỉ đúng với số dương, tôi sẽ sửa nó sau. @ipi cảm ơn!
flawr

1

Con trăn 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)))

Ung dung:

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.")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.