एक Phinary नंबर मानकीकृत करें


32

पृष्ठभूमि

यहाँ पर अधिकांश लोगों को कुछ पूर्णांक आधार प्रणालियों से परिचित होना चाहिए: दशमलव, बाइनरी, हेक्साडेसिमल, ऑक्टल। हेक्साडेसिमल प्रणाली में उदाहरण के लिए, एक नंबर abc.de 16 का प्रतिनिधित्व करते हैं

a*16^2 + b*16^1 + c*16^0 + d*16^-1 + e*16^-2

हालाँकि, कोई भी गैर-पूर्णांक आधारों का उपयोग कर सकता है, जैसे अपरिमेय संख्या। एक बार ऐसा आधार सुनहरा अनुपात (= (1 + /5) / 2 18 1.618 ... का उपयोग करता है । इन्हें पूर्णांक आधारों के अनुरूप परिभाषित किया गया है। तो एक संख्या abc.de φ (जहां एक से e पूर्णांक अंक हैं) का प्रतिनिधित्व करेगा

a*φ^2 + b*φ^1 + c*φ^0 + d*φ^-1 + e*φ^-2

ध्यान दें कि सिद्धांत में कोई भी अंक ऋणात्मक हो सकता है (हालाँकि हम इसके लिए अभ्यस्त नहीं हैं) - हम अग्रणी के साथ ऋणात्मक अंक का प्रतिनिधित्व करेंगे ~। इस सवाल हम से अंक के लिए अपने आप को प्रतिबंधित करने के उद्देश्य से ~9करने के लिए 9, तो हम स्पष्ट रूप से (बीच में टाइल्ड के साथ) एक स्ट्रिंग के रूप में एक नंबर लिख सकते हैं। इसलिए

-2*φ^2 + 9*φ^1 + 0*φ^0 + -4*φ^-1 + 3*φ^-2

के रूप में लिखा जाएगा ~290.~43। ऐसे नंबर को हम एक फाइलेर नंबर कहते हैं

एक फ़ाइनल संख्या को हमेशा मानक रूप में दर्शाया जा सकता है , जिसका अर्थ है कि प्रतिनिधित्व केवल अंकों का उपयोग करता है 1और 0, बिना 11कहीं भी शामिल है, और यह इंगित करने के लिए कि वैकल्पिक संख्या नकारात्मक है। (दिलचस्प रूप से, प्रत्येक पूर्णांक में मानक रूप में एक अद्वितीय परिमित प्रतिनिधित्व होता है।)

ऐसे मानक जो मानक रूप में नहीं हैं, उन्हें हमेशा निम्नलिखित टिप्पणियों का उपयोग करके मानक रूप में परिवर्तित किया जा सकता है:

  1. 011 φ = 100 φ (क्योंकि φ 2 = φ +1)
  2. 0200 φ = 1001 φ (क्योंकि φ 2 + 1 / φ = 2φ)
  3. 0 ~ 10 φ = ~ 101 φ (क्योंकि φ - 1 / φ = 1)

के अतिरिक्त:

  1. यदि सबसे महत्वपूर्ण अंक ~1(शेष संख्या मानक रूप के साथ) है, तो संख्या ऋणात्मक है, और हम इसे सभी को स्वैप करके 1और ~1शून्य से ऊपर के तीन नियमों को फिर से लागू करते हुए मानक स्वरूप में परिवर्तित कर सकते हैं। मानक रूप प्राप्त करें।

यहां इस तरह के सामान्यीकरण का एक उदाहरण दिया गया है (मैं सकारात्मक अंकों के लिए अतिरिक्त रिक्त स्थान का उपयोग कर रहा हूं, प्रत्येक अंक की स्थिति को संरेखित करने के लिए): 1~3.2~1φ

      1~3. 2~1φ         Rule:
=     0~2. 3~1φ         (3)
=    ~1~1. 4~1φ         (3)
=  ~1 0 0. 4~1φ         (3)
=  ~1 0 0. 3 0 1φ       (3)
=  ~1 0 1. 1 0 2φ       (2)
=  ~1 1 0. 0 0 2φ       (1)
=  ~1 1 0. 0 1 0 0 1φ   (2)
= - 1~1 0. 0~1 0 0~1φ   (4)
= - 0 0 1. 0~1 0 0~1φ   (3)
= - 0 0 1.~1 0 1 0~1φ   (3)
= - 0 0 0. 0 1 1 0~1φ   (3)
= - 0 0 0. 0 1 1~1 0 1φ (3)
= - 0 0 0. 0 1 0 0 1 1φ (3)
= - 0 0 0. 0 1 0 1 0 0φ (1)

उपज ।-0.0101φ

आगे पढ़ने के लिए, विकिपीडिया विषय पर एक बहुत ही जानकारीपूर्ण लेख है

चुनौती

इसलिए, या अन्यथा, एक प्रोग्राम या फ़ंक्शन लिखें, जो एक स्ट्रिंग को दिए गए एक फ़ाइनल नंबर (जैसा कि ऊपर वर्णित है), अपने मानक रूप का उत्पादन करता है, जो कि अग्रणी या अनुगामी शून्य के बिना। इनपुट में आवश्यक रूप से फ़ाइनल बिंदु नहीं होता है, लेकिन इसमें हमेशा बचे हुए अंक (इसलिए नहीं .123) होते हैं। आउटपुट में हमेशा फ़ाइनल बिंदु और उसके बाईं ओर कम से कम एक अंक शामिल होना चाहिए।

आप STDIN, ARGV या फ़ंक्शन तर्क के माध्यम से इनपुट ले सकते हैं और परिणाम को वापस कर सकते हैं या इसे STDOUT में प्रिंट कर सकते हैं।

आप उपरोक्त प्रक्रिया की तुलना में एक अलग एल्गोरिथ्म का उपयोग कर सकते हैं जब तक कि यह सिद्धांत रूप में सही और मनमाना (वैध) इनपुट के लिए सटीक हो - यानी, एकमात्र सीमा जो आपके कार्यान्वयन को संभावित रूप से तोड़ सकती है, वह तकनीकी सीमाएं होनी चाहिए जैसे कि बिल्ट-इन का आकार डेटा प्रकार या उपलब्ध रैम। उदाहरण के लिए, फ्लोटिंग-पॉइंट नंबर के रूप में इनपुट का मूल्यांकन करना और फिर अंकों को लालच से भरने की अनुमति नहीं है, क्योंकि किसी को इनपुट मिल सकता है जिसके लिए फ़्लोटिंग-पॉइंट अशुद्धियाँ गलत परिणाम देगी।

यह कोड गोल्फ है, सबसे छोटा उत्तर (बाइट्स में) जीतता है।

परीक्षण के मामलों

Input       Output

1           1.
9           10010.0101
1.618       10000.0000101
1~3.2~1     -0.0101
0.~1021     0. (or -0.)
105.~2      1010.0101
~31~5.~1    -100000.1001

अब मैं अपनी संख्याओं में ऋणात्मक अंकों का उपयोग करना चाहता हूं! 1 ~ 3 * 6 == 5 ~ 8
हारून

जवाबों:


6

जावास्क्रिप्ट (ईएस 6) - 446 418 422 420 बाइट्स

न्यूनतम किया गया:

F=s=>{D=[];z='000000000';N=t=n=i=e=0;s=(z+s.replace(/^([^.]*)$/,'$1.')+z).replace(/~/g,'-').replace(/-?\d/g,s=>((D[n++]=s/1),0));for(;i<n-3;i=j){if(p=D[j=i+1]){if(!e&&p<0){D=D.map(k=>-k);N=~N;p=-p}e=1}d=D[i];x=D[i+2];m=D[i+3];if(p<0){d--;p++;x++;e=j=0}if(p>1){d++;m++;p-=2;e=j=0}if(!d&&p*x==1){d=p;e=j=p=x=0}D[i]=d;D[i+1]=p;D[i+2]=x;D[i+3]=m}return(N?'-':'')+s.replace(/0/g,()=>D[t++]).replace(/^(0(?!\.))+|0+$/g,'')}

विस्तारित:

F = s => {
    D = [];
    z = '000000000';
    N = t = n = i = e = 0;
    s = (z + s.replace( /^([^.]*)$/, '$1.' ) + z).replace( /~/g, '-' ).
        replace( /-?\d/g, s => ((D[n++]=s/1),0) );

    for( ; i < n-3; i = j ) {
        if( p = D[j = i+1] ) {
            if( !e && p < 0 ) {
                D = D.map( k=>-k );
                N = ~N;
                p = -p;
            }
            e = 1;
        }
        d = D[i];
        x = D[i+2];
        m = D[i+3];

        if( p < 0 ) {
            d--;
            p++;
            x++;
            e = j = 0;
        }
        if( p > 1 ) {
            d++;
            m++;
            p-=2;
            e = j = 0;
        }
        if( !d && p*x == 1 ) {
            d = p;
            e = j = p = x = 0;
        }

        D[i] = d;
        D[i+1] = p;
        D[i+2] = x;
        D[i+3] = m;
    }

    return (N ? '-' : '') + s.replace( /0/g, ()=>D[t++] ).replace( /^(0(?!\.))+|0+$/g, '' );
}

कोड एक फ़ंक्शन का उत्पादन Fकरता है जो निर्दिष्ट रूपांतरण करता है।

यह गोल्फ के लिए एक कठिन समस्या है। कई एज केस रेंगते हैं जो कोड के सरलीकरण को रोकते हैं। विशेष रूप से, नकारात्मक से निपटना एक दर्द है, जो पार्सिंग के संदर्भ में और तार्किक हैंडलिंग के संदर्भ में दोनों है।

मुझे ध्यान देना चाहिए कि कोड केवल इनपुट की "उचित सीमा" को संभालता है। बाध्य बिना फ़ंक्शन के डोमेन का विस्तार करने के लिए, शून्य की संख्या zबढ़ाई जा सकती है, और निरंतर बाउंडिंग while( c++ < 99 )लूप को बढ़ाया जा सकता है। वर्तमान में समर्थित सीमा पहले ही आपूर्ति किए गए परीक्षण मामलों के लिए ओवरकिल है।

नमूना आउटपुट

F('1')          1.
F('9')          10010.0101
F('1~3.2~1')    -0.0101
F('0.~1021')    -0.
F('105.~2')     1010.0101
F('~31~5.~1')   -100000.1001

-0.सुंदर नहीं है, लेकिन इस सवाल का जवाब अभी भी सही है। यदि आवश्यक हो तो मैं इसे ठीक कर सकता हूं।


@ मार्टिनबटनर: आप कर सकते थे, लेकिन यह मुश्किल होगा। यह पूर्ण इनपुट पर "पास" की संख्या को सीमित करता है, और प्रत्येक पास में कई ऑपरेशन शामिल हैं। मेरी आंत महसूस करती है कि किसी भी n-digit इनपुट को सामान्य करने के लिए आवश्यक पास की संख्या कहीं nऔर के बीच होगी n log(n)। किसी भी मामले में, प्रत्येक वर्ण के लिए पास की संख्या को 10 के कारक द्वारा उठाया जा सकता है। zस्थिरांक में शून्य की संख्या भी एक दिलचस्प समस्या है। मुझे संदेह है कि 9 किसी भी संभावित इनपुट के लिए ओवरकिल है ।
सीओटीओ

@ मार्टिनबटनर: धन्यवाद। मैंने चरित्र वर्ग में पलायन को हटा दिया। के रूप में $0, जावास्क्रिप्ट इसका समर्थन नहीं करता है। या कम से कम फ़ायरफ़ॉक्स नहीं है। : पी
सीओटीओ

ठीक है, मुझे लगता है कि आपको बफर के रूप में 7 से अधिक अग्रणी जीरो की आवश्यकता नहीं है, लेकिन मुझे लगता है कि ट्रेलिंग जीरो का अनुमान लगाना थोड़ा कठिन होगा। बाहरी लूप के रूप में, मुझे नहीं लगता कि आपको इसकी आवश्यकता भी है, अगर आप बस थोड़ी देर के लिए लूप बनाते हैं (या लूप के लिए इसे आंतरिक रूप से एकीकृत करते हैं) और जब कोई अधिक परिवर्तन नहीं मिलता है, तो बस बाहर निकाल दें। मुझे लगता है कि मेरी कल्पना उस संबंध में थोड़ी स्पष्ट हो सकती है लेकिन "सिद्धांत रूप में सही और मनमाना (वैध) इनपुट्स के लिए सटीक है" मेरा मतलब था कि केवल सैद्धांतिक सीमा आपके अंतर्निहित डेटा प्रकारों / आपकी रैम का आकार होनी चाहिए।
मार्टिन एंडर

1
@COTO करने के लिए 1 बाइट बचाने के लिए, आप के पहले भाग जाने की कोशिश कर सकते हैं for( i = e = 0; i < n-3; i = j )द्वारा for(; i < n-3; i = j )और शीर्ष करने के लिए घोषणाओं ले जाते हैं, जा रहा है N = t = n = 0;के साथ बदल दियाN = t = n = i = e = 0;
इस्माइल मिगुएल

1
@IsmaelMiguel: के jमान पर स्थिर नहीं रखा जाता है i+1। तीन ifब्लॉकों में सूचना , jरीसेट करने के लिए है 0। इसलिए पहले ifब्लॉक के बाद किसी भी बिंदु पर इसका उपयोग प्रॉक्सी के रूप में नहीं किया जा सकता है i+1। चर iको केवल लूप के अंत तक (तीसरे कथन का उपयोग करके for) अपडेट नहीं किया जा सकता है क्योंकि लूप के अंत तक इसके मूल्य का सही उपयोग किया जाता है। लेकिन यह कहते हुए कि, शायद मुझे कुछ याद आ रहा है। यदि आप कोड को छोटा करने में सक्षम हैं, तो इसका परीक्षण करें, और सत्यापित करें कि यह अभी भी काम करता है, कृपया pastebin.com और यहां लिंक पर एक प्रति पोस्ट करें। मैं उत्तर में आपके लिए उचित क्रेडिट का विस्तार करूंगा। :)
सीओटीओ

2

हास्केल, 336 बाइट्स

z=[0,0]
g[a,b]|a*b<0=g[b,a+b]
g x=x<z
k![a,b,c,d]=[b,a+b,d-c+read k,c]
p('.':s)=1:0:2`drop`p s
p('~':k:s)=['-',k]!p s
p(k:s)=[k]!p s
p[]=1:0:z
[1,0]&y='.':z?y
[a,b]&y=[b,a+b]?y
x@[a,b]?y@[c,d]|x==z,y==z=""|g y='-':x?[-c,-d]|g[c-1,d]='0':x&[d,c+d]|g[c,d-1]='1':x&[d,c+d-1]|0<1=[b-a,a]?[d-c,c]
m[a,b,c,d]=[1,0]?[a*d+b*c-a*c,a*c+b*d]
f=m.p

इस लालची एल्गोरिथ्म है, लेकिन एक सटीक प्रतिनिधित्व के साथ [a,b]संख्याओं की एक + ( एक , ∈ ℤ) फ्लोटिंग प्वाइंट त्रुटियों से बचने के। g[a,b]परीक्षण कि क्या a + b + <0. उपयोग उदाहरण:

*Main> f "9"
"10010.0101"
*Main> f "1~3.2~1"
"-0.0101"
*Main> f "0.~1021"
"0."
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.