কোনও সংগীতের অভ্যন্তরের মাঝারি ব্যবধানগুলি মুদ্রণ করুন


10

পটভূমি

পশ্চিমা সংগীতে, প্রতিটি একক সংগীত নোটের একটি নির্দিষ্ট নাম রয়েছে। প্রতিটি অষ্টভের মধ্যে নীচের ক্রমে বারোটি অনন্য নোট রয়েছে: "সিসি # / ডিবি ডিডি # / এবি ইএফএফ # / জিবি জিজি # / আব এএ # / বিবি বি সি", যেখানে চূড়ান্ত সিটি প্রথমটির উপরে এক অক্টেভ।

বিভিন্ন অষ্টভের নোটের মধ্যে পার্থক্য বলতে, একটি সংখ্যা (একক অঙ্কে সীমাবদ্ধ এই চ্যালেঞ্জের জন্য) নোটের নামের শেষে যুক্ত হয়। সুতরাং, সি 5 হ'ল নোট যা সি 4 এর উপরে এক অক্টেভ। বিবি 6 বি 5 এর উপরে।

একটি গুরুত্বপূর্ণ তথ্য হ'ল বি 5 এবং সি 6 হ'ল নোট যা একে অপরের ঠিক পাশের, এবং সি 0 এবং বি 9 হ'ল সর্বনিম্ন এবং সর্বোচ্চ নোট।

যে কোনও দুটি নোটের মধ্যে একটি দূরত্ব রয়েছে যা তাদের মধ্যে সেমিটোন সংখ্যা। বিবি 4 বি 4 এর নীচে একটি সেমিটোন যা নিজে থেকে সি 5 এর নীচে একটি সেমিটোন। অষ্টভরে বারোটি সেমিটোন রয়েছে, সুতরাং বিবি 4 এটি # 3 থেকে 12 এর দূরত্ব, কারণ এটির উপরে একটি অষ্টক রয়েছে (লক্ষ্য করুন কীভাবে একটি নোটে দুটি নাম থাকতে পারে)।

চ্যালেঞ্জ

আপনার চ্যালেঞ্জটি হ'ল সংক্ষিপ্ততম প্রোগ্রামটি লিখুন যা STDIN থেকে সংগীত নোটগুলির একটি তালিকা নিতে পারে এবং অন্তর পরিবর্তনের তালিকাটি STDOUT এ মুদ্রণ করতে পারে।

ইনপুটটি সঙ্গীত নোটগুলির স্থান-বিভাজিত তালিকা হবে। প্রতিটি নোটে বড় হাতের অক্ষর এজি, একটি alচ্ছিক খ বা # চিহ্ন এবং একটি একক সংখ্যা থাকবে। আপনাকে 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. আপনার প্রোগ্রামে কেবল প্রিন্টযোগ্য এএসসিআইআই অক্ষর থাকা উচিত

  3. সংগীত বা শব্দ সম্পর্কিত কোনও বিল্ট-ইন ফাংশন আপনাকে ব্যবহার করার অনুমতি নেই

  4. এটি বাদে, স্ট্যান্ডার্ড কোড গল্ফ বিধি প্রযোজ্য


এটি মুদ্রণ করা উচিত +0বা -0বা 0একই রকম দুটি নোট জন্য?
হাওয়ার্ড

পছন্দ করুন
PhiNotPi

1
"বিবি 4 হ'ল বি 4 এর নীচে একটি সেমিটোন যা নিজে থেকে সি 4 এর নীচে একটি সেমিটোন"। আপনি এর শেষে সি 5 মানে, তাই না?
কীথ র্যান্ডাল

বাহ, এটা কখনই লক্ষ্য করিনি। ত্রুটি চিহ্নিত করার জন্য ধন্যবাদ। এটি এখন স্থির।
PhiNotPi

উত্তর:



4

হাস্কেল, ১1১ টি অক্ষর

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

আমি মনে করি এমন কিছু কৌশল যেগুলি উল্লেখযোগ্য:
১। argv[0](এখানে বলা হয় b) প্রোগ্রামটির নামের একটি পয়েন্টার, তবে এখানে স্ক্র্যাচ বাফার হিসাবে ব্যবহৃত হয়। আমাদের কেবল 4 বাইট (যেমন C#2\0) দরকার, তাই আমাদের পর্যাপ্ত পরিমাণ রয়েছে।
২. cআর্গুমেন্টের সংখ্যা, সুতরাং এটি 1 হিসাবে শুরু হয় (যখন তর্ক ছাড়াই চালানো হয়)। আমরা প্রথম দফায় মুদ্রণ প্রতিরোধ করতে এটি ব্যবহার করি।

সম্ভাব্য সমস্যা - একপ্রকারের c+=b[..c+=..]আজব is আমি মনে করি না এটি নির্ধারিত আচরণ, কারণ ?:এটি একটি সিকোয়েন্স পয়েন্ট, তবে সম্ভবত আমি ভুল করছি।


যদি আপনি এটি হিসাবে মনে করেন c = c + b[..c+=..]তবে এটি বেশ পরিষ্কারভাবে অপরিজ্ঞাত আচরণ। এর মধ্যে সিকোয়েন্সিং নির্বিশেষে [..], আপনি জানেন না যে cবাহিরটি আগে, সময় বা পরে আনা হয়েছিল কিনা b[..]
প্রশংসাপত্র

@ ফেফিয়েন্ট, আমি ধারণা করি যে তাত্ত্বিকভাবে একটি সংকলক করতে পারে REG=c;REG+=b[..c+=..];c=REG। তবে, আমি বাস্তবে এরকম কিছু দেখে অবাক হব। তবে এটি এখনও ইউবি।
ugoren

এটি কোড গল্ফ - 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)
হামার

আপনি বাদ দিতে পারেন আদর্শ
হোল্লেথ

খুব সুন্দর. কিছু পরামর্শ: 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)আরগভিটি দ্বারা 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 " " split(ব্যবহার করে splitting, না regexp)। তবে আউটপুট শেষে অতিরিক্ত স্থান রোধ করতে আমার আরও কোড যুক্ত করতে হবে।

আমি যদি অবহেলিত শব্দটি ব্যবহার করি তবে আমি 8 টি অক্ষর সাশ্রয় dupdকরে সংক্ষিপ্ত over [ - "%+d " printf ] dipকরতে পারি dupd - "%+d " printf। আমি অবহেলিত শব্দগুলি ব্যবহার করছি না কারণ সেগুলি "শীঘ্রই অপসারণের উদ্দেশ্যে করা হয়েছে"।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.