In các kích cỡ của các khoảng trong một bản nhạc


10

Lý lịch

Trong âm nhạc phương Tây, mỗi nốt nhạc đều có một tên được gán. Trong mỗi quãng tám, có mười hai ghi chú duy nhất theo thứ tự sau: "CC # / Db DD # / Eb EFF # / Gb GG # / Ab AA # / Bb B C", trong đó C cuối cùng là một quãng tám trên đầu tiên.

Để cho biết sự khác biệt giữa các ghi chú của các quãng tám khác nhau, một số (đối với thử thách này được giới hạn ở một chữ số) được thêm vào cuối tên ghi chú. Do đó, C5 là lưu ý là một quãng tám trên C4. Bb6 ở trên B5.

Một thực tế quan trọng là B5 và C6 là các ghi chú nằm ngay cạnh nhau và C0 và B9 là các ghi chú thấp nhất và cao nhất.

Giữa hai nốt bất kỳ, có một khoảng cách là số lượng nửa cung giữa chúng. Bb4 là một nửa cung dưới B4, chính nó là một nửa cung dưới C5. Có mười hai nửa cung trong một quãng tám, vì vậy Bb4 là khoảng cách 12 so với A # 3 vì nó là một quãng tám phía trên nó (chú ý cách một nốt nhạc có thể có tối đa hai tên).

Các thách thức

Thách thức của bạn là viết chương trình ngắn nhất có thể có một danh sách các ghi chú âm nhạc từ STDIN và in danh sách các thay đổi khoảng thời gian sang STDOUT.

Đầu vào sẽ là một danh sách các ghi chú âm nhạc được phân tách bằng không gian. Mỗi ghi chú sẽ bao gồm một chữ cái viết hoa AG, ký hiệu b hoặc # tùy chọn và một số có một chữ số. Bạn sẽ không phải đối phó với E # / Fb hoặc B # / Cb. Ví dụ đầu vào:

C4 D4 E4 F4 G4 A4 B4 C5 C4

Đầu ra sẽ là một danh sách các số nguyên được phân tách bằng dấu cách biểu thị khoảng cách giữa mỗi ghi chú liên tiếp, luôn được thêm tiền tố + hoặc - để hiển thị liệu ghi chú tăng dần hay giảm dần so với ghi chú trước đó. Sẽ luôn có một số ít xuất ra hơn ghi chú được nhập. Ví dụ đầu ra cho đầu vào trên:

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

Một số ví dụ đầu vào:

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

Và đầu ra tương ứng của họ:

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

Quy tắc và hạn chế

  1. Người chiến thắng được xác định bởi số lượng ký tự trong mã nguồn

  2. Chương trình của bạn chỉ bao gồm các ký tự ASCII có thể in

  3. Bạn không được phép sử dụng bất kỳ loại chức năng tích hợp nào có liên quan đến âm nhạc hoặc âm thanh

  4. Ngoài ra, áp dụng quy tắc golf tiêu chuẩn


Nó nên in +0hoặc -0hoặc 0hai ghi chú giống hệt nhau?
Howard

@Howard Vì tôi không chỉ định, một trong hai đều được chấp nhận.
PhiNotPi

1
"Bb4 là một nửa cung dưới B4, chính nó là một nửa cung dưới C4". Bạn có nghĩa là C5 ở cuối đó, phải không?
Keith Randall

Wow, không bao giờ nhận thấy rằng. Cảm ơn đã phát hiện ra lỗi. Bây giờ nó đã được sửa.
PhiNotPi

Câu trả lời:


6

GolfScript, 61

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

4

Haskell, 161 ký tự

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 ký tự

Dựa trên giải pháp của leftaroundabout, với một số cải tiến.

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

Một số thủ thuật mà tôi nghĩ là đáng nói:
1. argv[0](ở đây được gọi b) là một con trỏ đến tên chương trình, nhưng được sử dụng ở đây như một bộ đệm đầu. Chúng tôi chỉ cần 4 byte (ví dụ C#2\0), vì vậy chúng tôi có đủ.
2. clà số lượng đối số, vì vậy nó bắt đầu là 1 (khi chạy mà không có đối số). Chúng tôi sử dụng nó để ngăn chặn in trên vòng đầu tiên.

Vấn đề có thể xảy ra - c+=b[..c+=..]là loại lạ. Tôi không nghĩ đó là hành vi không xác định, bởi vì đó ?:là một điểm tuần tự, nhưng có lẽ tôi đã sai.


Nếu bạn nghĩ về nó như vậy c = c + b[..c+=..], thì đó là hành vi khá rõ ràng không xác định. Bất kể trình tự bên trong [..], bạn không biết liệu bên ngoài cđược tìm nạp trước, trong hoặc sau b[..].
ephemient

@ephemient, tôi đoán trong lý thuyết một trình biên dịch có thể làm REG=c;REG+=b[..c+=..];c=REG. Tuy nhiên, tôi sẽ ngạc nhiên khi thấy một cái gì đó như thế này trong thực tế. Nhưng nó vẫn là UB.
ugoren

Đó là Code Golf - chúng tôi đã gọi UB bằng cách sử dụng scanfmà không cần nguyên mẫu, và điều đó không sao. Nó chỉ là tốt để biết là gì và không phải là quy phạm pháp luật trong cuộc sống thực :)
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;}}

Thay vì tự làm dấu cộng, bạn chỉ có thể làm printf("%+d ",c-d).
hammar

Bạn có thể bỏ qua bao gồm ideone.com/G00fS
Hauleth

Rất đẹp. Một số gợi ý: F(*b-65)thay vì c-=65;, b[1]<36&&++c||b[1]>97&&c--?2:1-> b[1]&16?1:(c+=b[1]%2*2-1,2), lạm dụng argv bằng cách: main(e,b,c,d)char*b{(Sử dụng con trỏ đối số đầu tiên làm bộ đệm công việc).
ugoren

Một số khác - tôi nghĩ c=F(*b)%12có thể được thay thế bằng c=-~*b*1.6;c%=12. Tại sao? sintrong bản gốc Fcó thể được thay thế bằng 9.6. c*1.6+9.6(c+6)*1.6, c-=65(c+6)trở thành c-59, và sau đó c+1(60 * 96% 12 == 0).
ugoren

Cảm ơn tất cả những lời đề nghị! Chúng hoạt động tốt và làm cho nó ngắn hơn, nhưng tôi nghĩ rằng tôi sẽ rời khỏi nó như bây giờ; nó sẽ không thực sự là giải pháp của tôi nữa nếu không có sin.
đã ngừng quay ngược chiều

1

Yếu tố, 303 ký tự

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

Với nhận xét,

! 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.

Đối với tập lệnh này, "danh sách được phân tách bằng dấu cách" có thể có 1 hoặc nhiều khoảng trắng giữa các phần tử và 0 hoặc nhiều khoảng trắng ở đầu hoặc cuối. Kịch bản lệnh này không in thêm một khoảng trống ở cuối đầu ra, nhưng nó cũng chấp nhận một khoảng trắng thừa (hoặc dòng mới) ở cuối đầu vào.

Nếu tôi chấp nhận một định nghĩa chặt chẽ hơn, trong đó "danh sách được phân tách bằng dấu cách" có chính xác 1 khoảng trắng giữa các phần tử và 0 khoảng trắng ở đầu hoặc cuối, thì tôi có thể rút ngắn contents R/ [#-b]+/ all-matching-slicesthành contents " " split(sử dụng splitting, không regexp). Tuy nhiên, tôi sẽ cần thêm nhiều mã hơn để ngăn không gian thừa ở cuối đầu ra.

Nếu tôi sử dụng từ không dùng nữa dupd, tôi có thể rút ngắn over [ - "%+d " printf ] diplại dupd - "%+d " printf, lưu 8 ký tự. Tôi không sử dụng những từ bị phản đối vì chúng "dự định sẽ sớm bị xóa".

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.