संगीत के एक टुकड़े के अंदर अंतराल के आकार को प्रिंट करें


10

पृष्ठभूमि

पश्चिमी संगीत में, हर एक संगीत नोट में एक निर्दिष्ट नाम होता है। प्रत्येक सप्तक के भीतर, निम्नलिखित क्रम में बारह अनोखे नोट हैं: "CC # / Db DD # / Eb EFF # / Gb GG # / Ab AA # / Bb B C", जहां अंतिम C पहले के ऊपर एक सप्तक है।

अलग-अलग सप्तक के नोटों के बीच अंतर बताने के लिए, नोट के नाम के अंत में एक संख्या (एकल अंक तक सीमित इस चुनौती के लिए) को जोड़ा जाता है। इस प्रकार, C5 नोट है जो C4 के ऊपर एक सप्तक है। Bb6 B5 से ऊपर है।

एक महत्वपूर्ण तथ्य यह है कि बी 5 और सी 6 ऐसे नोट हैं जो एक दूसरे के ठीक बगल में हैं, और यह कि C0 और B9 सबसे कम और उच्चतम नोट हैं।

किसी भी दो नोटों के बीच, एक दूरी होती है, जो उनके बीच के सेमिटोन्स की संख्या होती है। B4, B4 के नीचे एक अर्धविराम है, जो C5 के नीचे स्वयं एक अर्धविराम है। एक सप्तक में बारह अर्धवृत्त हैं, इसलिए Bb4 A # 3 से 12 की दूरी पर है क्योंकि यह ऊपर एक सप्तक है (ध्यान दें कि एक नोट में दो नामों तक कैसे हो सकता है)।

चुनौती

आपकी चुनौती सबसे कम संभव कार्यक्रम लिखना है जो एसटीडीआईएन से संगीत नोटों की एक सूची ले सकता है और एसटीडीयूएसटी में अंतराल परिवर्तनों की सूची प्रिंट कर सकता है।

इनपुट संगीत नोटों की एक अलग-अलग सूची होगी। प्रत्येक नोट में एक अपरकेस अक्षर एजी, एक वैकल्पिक बी या # साइन, और एक एकल अंक संख्या शामिल होगी। आपको E # / Fb या B # / Cb से नहीं निपटना पड़ेगा। उदाहरण इनपुट:

C4 D4 E4 F4 G4 A4 B4 C5 C4

आउटपुट पूर्णांकों की एक अलग-अलग-अलग सूची होगी जो प्रत्येक क्रमिक नोट के बीच की दूरी का प्रतिनिधित्व करती है, हमेशा एक + या - के साथ उपसर्ग करती है यह दिखाने के लिए कि क्या नोट एक से पहले आरोही या अवरोही के सापेक्ष था। हमेशा इनपुट किए गए नोटों की तुलना में एक कम संख्या में आउटपुट होगा। उपरोक्त इनपुट के लिए उदाहरण आउटपुट:

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

कुछ और उदाहरण इनपुट:

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

और उनके अनुरूप आउटपुट:

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

नियम और प्रतिबंध

  1. स्रोत कोड में वर्णों की संख्या से विजेता निर्धारित होता है

  2. आपके कार्यक्रम में केवल मुद्रण योग्य ASCII वर्ण शामिल होने चाहिए

  3. आपको किसी भी प्रकार के अंतर्निहित फ़ंक्शन का उपयोग करने की अनुमति नहीं है जो संगीत या ध्वनि से संबंधित है

  4. इसके अलावा, मानक कोड गोल्फ नियम लागू होते हैं


इसे प्रिंट चाहिए +0या -0या 0दो समान नोट्स के लिए?
हॉवर्ड

@ जब से मैंने निर्दिष्ट नहीं किया है, या तो एक स्वीकार्य है।
PhiNotPi

1
"बी 4, बी 4 के नीचे एक अर्धविराम है, जो कि सी 4 के नीचे स्वयं एक अर्धांश है"। आपका मतलब है कि सही, अंत में C5?
कीथ रान्डेल

वाह, कभी गौर नहीं किया। त्रुटि को स्पॉट करने के लिए धन्यवाद। यह अब तय हो गया है।
PhiNotPi

जवाबों:



4

हास्केल, 161 वर्ण

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

पर्ल, 103

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

3

सी, 123 वर्ण

कुछ सुधारों के साथ लेफ्टअराउंडआउट के समाधान के आधार पर।

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

कुछ ट्रिक्स जो मुझे लगता है कि उल्लेख के लायक हैं:
1. argv[0](यहां कहा जाता है b) प्रोग्राम नाम का एक संकेतक है, लेकिन यहां एक स्क्रैच बफर के रूप में उपयोग किया जाता है। हमें केवल 4 बाइट्स (जैसे C#2\0) चाहिए, इसलिए हमारे पास पर्याप्त है।
2. cतर्कों की संख्या है, इसलिए यह 1 के रूप में शुरू होता है (जब बिना तर्क के चलाया जाता है)। हम इसका उपयोग पहले दौर पर मुद्रण को रोकने के लिए करते हैं।

संभावित समस्या - c+=b[..c+=..]अजीब तरह की है। मुझे नहीं लगता कि यह अपरिभाषित व्यवहार है, क्योंकि ?:यह एक अनुक्रम बिंदु है, लेकिन शायद मैं गलत हूं।


यदि आप इसके बारे में सोचते हैं c = c + b[..c+=..], तो यह स्पष्ट रूप से अपरिभाषित व्यवहार है। सीक्वेंसिंग के बावजूद [..], आप यह नहीं जानते कि बाहरी cको पहले, दौरान या बाद में लाया जाता है या नहीं b[..]
अपरिमेय

@ कुशल, मुझे लगता है कि सिद्धांत रूप में एक संकलक कर सकता है REG=c;REG+=b[..c+=..];c=REG। हालांकि, मैं इस तरह के व्यवहार को देखकर आश्चर्यचकित रहूंगा। लेकिन यह अभी भी यूबी है।
बदसूरत

यह कोड गोल्फ है - हमने पहले ही scanfएक प्रोटोटाइप के बिना यूबी का उपयोग किया है, और यह ठीक है। यह जानना अच्छा है कि वास्तविक जीवन में क्या कानूनी है और क्या कानूनी नहीं है :)
विशेषण

2

सी, 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;}}

प्लस साइन करने के बजाय, आप बस कर सकते हैं printf("%+d ",c-d)
हमार

आप
Hauleth

बहुत अच्छा। कुछ सुझाव: के F(*b-65)बजाय c-=65;, b[1]<36&&++c||b[1]>97&&c--?2:1-> b[1]&16?1:(c+=b[1]%2*2-1,2), दुर्व्यवहार argv द्वारा: main(e,b,c,d)char*b{(एक काम बफर के रूप में पहला तर्क सूचक का उपयोग करें)।
ugoren

एक और एक - मुझे लगता है कि c=F(*b)%12इसके साथ प्रतिस्थापित किया जा सकता है c=-~*b*1.6;c%=12। क्यों? sinमूल में F9.6 के साथ प्रतिस्थापित किया जा सकता है। c*1.6+9.6है (c+6)*1.6, c-=65और (c+6)बन गया है c-59, और फिर c+1(60 * 96% 12 == 0)।
ugoren

सभी सुझावों के लिए शुक्रिया! वे ठीक काम करते हैं और इसे कम करते हैं, लेकिन मुझे लगता है कि मैं इसे छोड़ दूँगा क्योंकि यह अब है; यह वास्तव में साइन के बिना अब मेरा समाधान नहीं होगा।

1

कारक, 303 वर्ण

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

टिप्पणियों के साथ,

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

इस स्क्रिप्ट के लिए, "स्पेस-सेपरेटेड लिस्ट" में तत्वों के बीच 1 या अधिक स्पेस और शुरुआत या अंत में 0 या अधिक स्पेस हो सकते हैं। यह स्क्रिप्ट आउटपुट के अंत में एक अतिरिक्त स्थान प्रिंट करता है, लेकिन यह इनपुट के अंत में एक अतिरिक्त स्थान (या न्यूलाइन) को भी स्वीकार करता है।

अगर मैं एक कड़ी परिभाषा को अपनाऊंगा, जहां "स्पेस-सेपरेटेड लिस्ट" में तत्वों के बीच बिल्कुल 1 स्पेस है, और शुरुआत या अंत में 0 स्पेस हैं, तो मैं (उपयोग , नहीं ) contents R/ [#-b]+/ all-matching-slicesको छोटा कर सकता हूं । हालांकि, आउटपुट के अंत में अतिरिक्त स्थान को रोकने के लिए मुझे अधिक कोड जोड़ने की आवश्यकता होगी।contents " " splitsplittingregexp

अगर मैं पदावनत शब्द का उपयोग dupd, मैं छोटा कर सकते हैं over [ - "%+d " printf ] dipकरने के लिए dupd - "%+d " printf, 8 वर्णों की बचत। मैं पदावनत शब्दों का उपयोग नहीं कर रहा हूं क्योंकि वे "जल्द ही हटाए जाने का इरादा रखते हैं।"

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.