Bir müzik parçasının içindeki aralıkların boyutlarını yazdırın


10

Arka fon

Batı müziğinde her müzik notasının atanmış bir adı vardır. Her oktav içinde, aşağıdaki sırayla on iki benzersiz not vardır: "CC # / Db DD # / Eb EFF # / Gb GG # / Ab AA # / Bb B C", burada son C birinciden bir oktavdır.

Farklı oktavların notları arasındaki farkı söylemek için, not adının sonuna bir sayı (tek bir rakamla sınırlandırılmış bu meydan okuma için) eklenir. Dolayısıyla C5, C4'ün üzerinde bir oktav olan nottur. Bb6, B5'in üzerindedir.

Önemli bir gerçek, B5 ve C6'nın yan yana olan notlar olduğu ve C0 ve B9'un en düşük ve en yüksek notalar olduğudur.

Herhangi iki nota arasında, aralarındaki yarı tonların sayısı olan bir mesafe vardır. Bb4, C4'ün altında bir yarı ton olan B4'ün altında bir yarı tondur. Bir oktavda on iki yarı ton vardır, bu nedenle Bb4, A # 3'ten 12 mesafedir, çünkü üzerinde bir oktav vardır (tek bir notun en fazla iki isme sahip olabileceğine dikkat edin).

Meydan okuma

Zorluğunuz STDIN'den müzik notalarının bir listesini alabilecek ve aralık değişiklikleri listesini STDOUT'a yazdırabilecek en kısa programı yazmaktır.

Giriş, boşlukla ayrılmış müzik notalarının bir listesi olacaktır. Her not bir büyük harf AG, isteğe bağlı bir b veya # işaretinden ve tek haneli bir rakamdan oluşacaktır. E # / Fb veya B # / Cb ile uğraşmak zorunda kalmayacaksınız. Örnek girdi:

C4 D4 E4 F4 G4 A4 B4 C5 C4

Çıktı, her ardışık nota arasındaki mesafeyi temsil eden ve notanın kendisinden önceki sayıya göre artan mı yoksa azalan mı olduğunu göstermek için her zaman + veya - ile ön ekli olarak boşlukla ayrılmış bir tamsayı listesi olacaktır. Girilen notlardan her zaman daha az bir sayı verilir. Yukarıdaki giriş için örnek çıktı:

+2 +2 +1 +2 +2 +2 +1 -12

Bazı örnek girişler:

E5 D#5 E5 B4 E5 F#5 E5 B4
C0 B0 Bb1 A2 G#3 G4 F#5 F6
G4 Ab4 Gb4 A4 F4 A#4

Ve ilgili çıktıları:

-1 +1 -5 +5 +2 -2 -5
+11 +11 +11 +11 +11 +11 +11
+1 -2 +3 -4 +5

Kurallar ve Kısıtlamalar

  1. Kazanan, kaynak koddaki karakter sayısına göre belirlenir

  2. Programınız yalnızca yazdırılabilir ASCII karakterlerden oluşmalıdır

  3. Müzik veya sesle ilgili herhangi bir yerleşik işlevi kullanmanıza izin verilmiyor

  4. Bunun dışında standart kod golf kuralları geçerlidir


Yazdırmalı +0-0yoksa 0iki özdeş not mu?
Howard

@Howard Belirtmediğim için ikisinden biri kabul edilebilir.
PhiNotPi

1
"Bb4, kendisi C4'ün altında bir yarı ton olan B4'ün altında bir yarı tondur". Bunun sonunda C5 demek istiyorsun, değil mi?
Keith Randall

Vay canına, bunu hiç fark etmedim. Hatayı tespit ettiğiniz için teşekkür ederiz. Şimdi düzeltildi.
PhiNotPi

Yanıtlar:


6

GolfScript, 61

" "/{)12*\{"bC#D EF G A B"?(+}/}%(\{.@-.`\0>{"+"\+}*\}/;]" "*

4

Haskell, 161 karakter

f(c:r)=maybe(12*read[c])(+f r).lookup c$zip"bC#D.EF.G.A.B"[-1..]
g n|n<0=show n|1<3='+':show n
h x=zipWith(-)(tail x)x
main=interact$unwords.map g.h.map f.words

4

Perl, 103

#!/usr/bin/perl -an
/.((b)|(\D))?/,(($~,$,)=($,,12*$'+ord()%20%7*2+(ord()%7>3)-$-[2]+$-[3]))[0]&&printf'%+d ',$,-$~for@F

3

C, 123 karakter

Leftaroundabout'un çözümüne dayanarak, bazı iyileştirmelerle.

main(c,b,d)
    char*b;
{
    while(d=c,~scanf("%s",b)?c=-~*b*1.6,c%=12,c+=b[~b[1]&16?c+=1-b[1]/40,2:1]*12:0)
        d>1&&printf("%+d ",c-d);
}

Bazı hileler bahsetmeye değer:
1. argv[0](burada denir b) program adına bir işaretçi, ancak burada bir çizik tamponu olarak kullanılır. Sadece 4 bayta (örn. C#2\0) İhtiyacımız var, bu yüzden yeterli var.
2. cbağımsız değişkenlerin sayısıdır, bu nedenle 1 olarak başlar (bağımsız değişkenler olmadan çalıştırıldığında). İlk turda yazdırmayı önlemek için kullanıyoruz.

Olası sorun - c+=b[..c+=..]biraz garip. Tanımlanmamış bir davranış olduğunu düşünmüyorum, çünkü ?:bir sıralama noktası, ama belki de yanılıyorum.


Eğer bunu düşünüyorsanız, c = c + b[..c+=..]oldukça açık bir şekilde tanımlanmamış bir davranıştır. İçindeki sıralamadan bağımsız olarak, [..]dış ckısmın önce, sırasında veya sonrasında getirilip getirilmediğini bilmiyorsunuz b[..].
ephemient

@efemient, sanırım teoride bir derleyici yapabilirdi REG=c;REG+=b[..c+=..];c=REG. Ancak pratikte böyle bir şey gördüğüme şaşıracağım. Ama hala UB.
ugoren

Bu Code Golf - UB'yi scanfprototipsiz kullanarak zaten çağırdık ve sorun değil. Gerçek hayatta neyin yasal olduğunu ve neyin yasal olmadığını bilmek güzel :)
ephemient

2

C 241 229 183

F(c){c-=65;return c*1.6+sin(c/5.+.3)+9;}
#define r if(scanf("%s",b)>0){c=F(*b)%12;c+=b[b[1]<36&&++c||b[1]>97&&c--?2:1]*12
main(e,c,d){char b[4];r;}s:d=c;r;printf("%+d ",c-d);goto s;}}

Artı işaretini kendiniz yapmak yerine, yapabilirsiniz printf("%+d ",c-d).
Hamar

Şunları yapabilirsiniz omit içeren ideone.com/G00fS
Hauleth

Çok hoş. Bazı öneriler: F(*b-65)yerine c-=65;, b[1]<36&&++c||b[1]>97&&c--?2:1-> b[1]&16?1:(c+=b[1]%2*2-1,2), kötüye Argv: main(e,b,c,d)char*b{(çalışma tamponu olarak ilk değişken işaretçiyi kullanarak).
ugoren

Başka bir tane - Bence c=F(*b)%12değiştirilebilir c=-~*b*1.6;c%=12. Neden? sinorijinalde F9.6 ile değiştirilebilir. c*1.6+9.6olan (c+6)*1.6, c-=65ve (c+6)olmak c-59ve daha sonra c+1(60 *% 96 12 == 0).
ugoren

Tüm öneriler için teşekkürler! İyi çalışıyorlar ve daha kısa yapıyorlar, ama sanırım şimdi olduğu gibi bırakacağım; sinüs olmasaydı artık benim çözümüm olmayacaktı.
counterclockwis'i

1

Faktör, 303 karakter

USING: combinators formatting io kernel math regexp sequences ;
f contents R/ [#-b]+/ all-matching-slices
[ 0 swap [ {
{ [ dup 48 < ] [ drop 1 ] }
{ [ dup 65 < ] [ 48 - 12 * ] }
{ [ dup 98 < ] [ "C-D-EF-G-A-B" index ] }
[ drop -1 ]
} cond + ] each
swap [ over [ - "%+d " printf ] dip ] when* ] each drop

Yorumlarla,

! combinators => cond
! formatting => printf
! io => contents
! kernel => swap dup drop over dip when*
! math => < - * +
! regexp => R/ all-matching-slices
! sequences => each
USING: combinators formatting io kernel math regexp sequences ;

f       ! Push false, no previous note value.

! Find notes (as string slices) in standard input. The golfed regexp
! R/ [#-b]+/ matches all notes and no whitespace.
contents R/ [#-b]+/ all-matching-slices

! For each string slice:
[
    0       ! Push 0, initial note value.
    swap    ! Move note slice to top of stack, above note value.

    ! For each Unicode codepoint in note:
    [
        ! Convert the Unicode codepoint to its value in semitones.
        ! For golf, [ 48 ] is shorter than [ CHAR: A ].
        {
            ! Sharp # {35} has 1 semitone.
            { [ dup 48 < ] [ drop 1 ] }
            ! 0-9 {48-57} has 0 to 9 octaves (1 octave = 12 semitones).
            { [ dup 65 < ] [ 48 - 12 * ] }
            ! A-G {65-71} has 0 to 11 semitones.
            { [ dup 98 < ] [ "C-D-EF-G-A-B" index ] }
            ! Flat b {98} has -1 semitone.
            [ drop -1 ]
        } cond

        +       ! Add semitones to cumulative note value.
    ] each

    swap    ! Move previous note value to top of stack.
    ! When there is a previous note value:
    [
        ! Keep current note on stack.
        over [
            ! Compute and print interval.
            - "%+d " printf
        ] dip
    ] when*
    ! Current note replaces previous note at top of stack.
] each

drop    ! Drop previous note, so stack is empty.

Bu komut dosyası için, "boşlukla ayrılmış liste" öğelerinin arasında 1 veya daha fazla boşluk ve başında veya sonunda 0 veya daha fazla boşluk olabilir. Bu komut dosyası, çıktı sonunda fazladan bir boşluk yazdırır, ancak giriş sonunda fazladan bir boşluk (veya yeni satır) kabul eder.

Bir "alan ayrılmış bir listesi" elemanları arasında tam olarak 1 alanı ve başında ya da sonunda 0 boşluk içermeyen katı bir tanımı, kabul olur, o zaman kısaltabilir contents R/ [#-b]+/ all-matching-slicesiçin contents " " split(kullanarak splittingdeğil regexp). Ancak, çıkış sonunda fazladan boşluk önlemek için daha fazla kod eklemek gerekir.

Ben kaldırılan kelimesini kullanırsanız dupd, ben kısaltabilir over [ - "%+d " printf ] dipiçin dupd - "%+d " printf8 karakter tasarruf. Kullanımdan kaldırılmış kelimeler kullanmıyorum çünkü "yakında kaldırılması planlanıyor".

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.