Akort Dizeleri


9

Görev

Belirli bir frekansa ayarlanmış ve belirli bir noktaya bastırılmış bir telin ayarlanmış kaç senti ile birlikte çalınan notayı belirlemek için bir program yazın.

Basitlik amacıyla, üretilen sesin frekansının ve basıldığı yerin sağındaki ipin uzunluğunun ters orantılı olduğunu varsayın.

Not: Bu görev tonları / diğer harmonikleri değil, yalnızca temel tonu ele alır.

Giriş

Programınıza iki veri parçası verilir:

  • Söz konusu dizeyi temsil eden rastgele uzunluktaki bir dize. Bu dize, dizenin basılı tutulacağı bir X ile işaretlenir.

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

    Notun, dizenin sağındaki dize kısmı kullanılarak çalındığını varsayın X.

  • Dizenin ayarlanma sıklığını gösteren bir sayı (ille de bir tamsayı değil). Bu sayının kesinliği ondalık basamaktan sonra en fazla dört basamak olacaktır.

Geçilen frekansların 10 Hzve arasında olduğu varsayılabilir 40000 Hz.

Giriş, seçtiğiniz bir biçimde geçirilebilir. Lütfen cevabınızda programınıza girdinin nasıl kabul edileceğini belirtin.

Çıktı

Programınız, hem on iki tonlu eşit mizaç ayarlama sistemindeki en yakın notayı * hem de dizeyle belirtilen sesin (en yakın kuruşa yuvarlanmış) en yakın notadan uzak sent sayısını çıkarmalıdır.

+nsent n, notanın keskin / üstünde sentleri ve notun -ndüz / altında sentleri belirtmek için kullanılmalıdır .

Not bilimsel adım notasyonunda verilmelidir. A4'ün ayarlandığını varsayın 440Hz. Düz / keskin notlar için b ve # tuşlarını kullanın. Not: Keskin ya da düz kullanılabilir. Nota için 466.16Hz, ya A#ya Bbnot için çıkış olarak verilebilecektir.

Çıktıda yalnızca daha önce belirtilen iki bilgi parçası olduğu sürece çıktının biçimi size bağlıdır (örneğin, olası her çıktının yazdırılmasına izin verilmez).

* en yakın nota, sent sayısı ile ölçülen, giriş tarafından belirtilen sese en yakın notayı ifade eder (bu nedenle, 50 centssesin içindeki nota ). Ses 50 centsiki farklı notadan uzaksa (yuvarlamadan sonra), iki notadan biri verilebilir.

Örnekler

Programınız yalnızca aşağıdaki örnekler için değil, tüm durumlar için çalışmalıdır.

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

* Keskin veya düz çıkmış olabilir.

Potansiyel Olarak Faydalı Bağlantılar

Bu en kısa cevap kazanır.


Örneklerinizin biraz tutarsız olduğunu düşünüyorum: Birincisine göre [--X--], dize xyerleştirildiği bölümün ortasında basılırken, sonuncusu [-X--]bu mantığı izlerken 3/8 (2/5 değil) olur. Yoksa yanlış bir şey mi anlıyorum?
flawr

Sonuncusu için @flawr [-X--], dize 4 yere bölünür (ve bu nedenle 5 parçaya) ve bu bölümlerin ikincisinde bastırılır. Böylece, tuşuna basılır 2/5ve kullanılan uzunluk olur 3/5.
es1024

Ah tamam şimdi anlıyorum, bu yüzden her biri -temelde bölümlerin konumunu temsil ediyor, açıkladığınız için teşekkürler!
flawr

Yanıtlar:


1

BBC Basic, 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'

Puan yorumları içermez. Henüz golf oynamadı.

Çıktı

İki uzun hariç tüm test durumlarında doğru performans gösterir. İçin Eb9bunun deney durumda eksik bir çizgi var gibi görünüyor: 22 vardır -ve bir tane X24 eşit parçaya böler dize. Manuel hesaplamalarıma göre, bu 9600Hz, D9'dan 37 sent yukarıda. Programımın çıktısı tam olarak bu. Başka bir çizgi eklersem Eb9 + 8 sent alırım. Maalesef BBC Basic 255 karakterden uzun karakter dizilerini işleyemez, bu nedenle Eb11durum hata verir.

resim açıklamasını buraya girin


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

Ascii resmini tek bir hatta ve frekansı ayrı bir çizgide alır.

Birkaç karakter sihirli sayılarının doğruluğunu azaltarak bırakılabilir 17.3123ve 57.376.

Golf olmadan, program şöyle görünür:

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
Harika scanfbiçim dizesi için +1 . Bunu yapabileceğine dair hiçbir fikrim yoktu. Daha sonra sana çıkış kodunu kontrol eder (ı C ve benzeri bir şey çıkışı için aklıma rağmen, ben rekabetçi şeyi yapmak için bir yol göremiyordu bunu düşündüm.) Ben varsayalım d+9üzerinde endeksli çünkü olduğunu A notu, oktav sayısını C notundaki dizine ayarlamanız gerekir: Acaba bunun bir yolu var mı?
Level River St

Evet, +9 oktavların C'de başlamasını telafi eder. Ya bu ya da not adının hesaplanmasına benzer bir düzeltme yapar. Not adları için, dairesel kaydırma bir LUT tarafından uygulanabilir, ancak bunları hesaplamanın daha "matematiksel" yolunu seviyorum.
anatolyg

1

JavaScript (199)

Örneğin, 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)}

Sabit. (Avrupa'da yaşadığım için Bb yerine B ve B = yerine H kullandım)


Flawr, Alman mısın? B ve H'yi her zaman bir Avrupa gösterimi olarak değil, bir Alman gösterimi olarak düşündüm. İngiltere ve İrlanda Bb ve B kullanır. İspanya ve İtalya SIb ve SI kullanır (DO RE MI FA SOL LA SI'da olduğu gibi). Her neyse, bu sadece bir karakterin kaydedilmesi.
Level River St

Evet Almanca konuşulan bir ülkeyim, diğer Avrupa ülkelerinin bu Doremi sistemini kullandığının farkında değildim (sadece insanların çocuk eğitiminde kullandığını duydum). Her neyse, ilk başta bir şakaydı çünkü söylediğin gibi sadece 1 karakter kaydeder ve gereksinimleri gerçekten karşılamaz =)
Kusur

Eğer sent sayısı negatifse (örneğin, t('[---X--]',11.7103)(son örnek) -10,-11
es1024

Kullanmak p="C0C#0D0D#0E0F0F#0G0G#0A0B0H".split(0)size ek 2 karakter kazandırır.
Sean Latham

@ es1024 Bilmeliydim: Bunun nedeni round(x) = x+.5|0, yalnızca pozitif sayılar için doğru olan yuvarlak işlevi uyguladığım için , bunu daha sonra çözeceğim. @ipi teşekkürler!
flawr

1

Python 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)))

Ungolfed:

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.")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.