निकटतम अंश


24

कार्य:

आपके कार्यक्रम को प्रारूप में एक उचित , सकारात्मक सरल अंश दिया गया है <numerator>/<denominator>

इस इनपुट के लिए, इसे दो अंश ढूंढने होंगे।

  1. एक अंश जो इनपुट से कम है।
  2. एक अंश जो इनपुट से अधिक है।

दोनों अंशों में इनपुट की तुलना में कम भाजक होना चाहिए। सभी संभावित अंशों में, उन्हें इनपुट में सबसे कम अंतर होना चाहिए।

आउटपुट:

आपके प्रोग्राम का आउटपुट होना चाहिए:

  • एक अंश जो प्रारूप में इनपुट से छोटा है <numerator>/<denominator>
  • एक अंतरिक्ष चरित्र (एएससीआईआई-कोड 32) द्वारा पीछा किया गया।
  • एक ऐसे अंश द्वारा अनुसरण किया जाता है जो प्रारूप में इनपुट से अधिक है <numerator>/<denominator>

निम्नलिखित नुसार:

«fraction that is < input» «fraction that is > input»

नियम:

  • आउटपुट किए गए सभी अंश न्यूनतम शर्तों में होने चाहिए ।
  • आउटपुट किए गए सभी अंश उचित फ्रैक्चर होने चाहिए।
  • यदि कोई उचित अंश संभव नहीं हैं जो नियमों द्वारा अनुमत हैं, तो आपको 0एक अंश <इनपुट के बजाय आउटपुट और 1एक अंश> इनपुट के बजाय आउटपुट करना होगा ।
  • आप चुन सकते हैं कि आप अंश को कमांड-लाइन तर्क (जैसे yourprogram.exe 2/5) के रूप में प्राप्त करना चाहते हैं या उपयोगकर्ता इनपुट के लिए संकेत दें।
  • आप मान सकते हैं कि आपका कार्यक्रम अमान्य इनपुट प्राप्त नहीं करेगा।
  • सबसे छोटा कोड (बाइट्स में, किसी भी भाषा में) जीतता है।
  • कोई भी गैर-मानक कमांड-लाइन तर्क (तर्क जो आमतौर पर स्क्रिप्ट चलाने के लिए आवश्यक नहीं हैं) कुल वर्ण गणना की ओर गिनते हैं।

  • आपका कार्यक्रम क्या नहीं करना चाहिए :

    • किसी भी बाहरी संसाधनों पर निर्भर।
    • एक विशिष्ट फ़ाइल नाम होने पर निर्भर करता है।
    • आवश्यक आउटपुट के अलावा कुछ भी आउटपुट करें।
    • असाधारण रूप से लंबे समय तक चलना। यदि आपका प्रोग्राम 179565/987657औसत घरेलू उपयोगकर्ता के कंप्यूटर पर 6-अंकीय अंश और हर (जैसे ) के साथ अंशों के लिए एक मिनट से अधिक चलता है , तो यह अमान्य है।
    • 0हर के साथ आउटपुट भिन्न। आप शून्य से विभाजित नहीं कर सकते।
    • अंश के 0रूप में आउटपुट अंश। आपके प्रोग्राम को 0कुछ अंश के बजाय आउटपुट होना चाहिए ।
    • एक इनपुट किए गए अंश को कम करें। यदि इनपुट के रूप में दिया गया अंश रिड्यूसबल है, तो आपको इनपुट के रूप में भिन्न का उपयोग करना होगा।
  • आपके प्रोग्राम को एक प्रोग्रामिंग भाषा में नहीं लिखा जाना चाहिए, जिसके लिए इस चुनौती को पोस्ट करने से पहले सार्वजनिक रूप से उपलब्ध संकलक / दुभाषिया मौजूद नहीं था।

उदाहरण:

इनपुट: 2/5
आउटपुट: 1/3 1/2

इनपुट: 1/2
आउटपुट: 0 1

इनपुट: 5/9
आउटपुट: 1/2 4/7

इनपुट: 1/3
आउटपुट: 0 1/2

इनपुट: 2/4
आउटपुट: 1/3 2/3

इनपुट: 179565/987657
आउटपुट: 170496/937775 128779/708320


1
आपका पहला उदाहरण विनिर्देश से मेल नहीं खाता है: दोनों अंशों में इनपुट की तुलना में कम भाजक होना चाहिए।
हावर्ड

1
पहला उदाहरण, आउटपुट होना चाहिए 1/3 1/2
हेइको ओबर्डिएक

@HeikoOberdiek तुम सही हो। फिक्स्ड।
user2428118

1
"औसत घरेलू उपयोगकर्ता के कंप्यूटर" को परिभाषित करें। 1.6GHz इंटेल एटम मशीन पर 90 सेकंड स्वीकार्य है?
जॉन ड्वोरक

2
आपका अंतिम उदाहरण गलत है। इनपुट अंश आउटपुट फ्रैक्शंस के पहले के बराबर होता है।
डेविड सी सी

जवाबों:


3

ऋषि - 119 117

x,X=map(int,raw_input().split('/'))
a=0
A=c=C=1
while C<X:exec("ab,,AB"[c*X>C*x::2]+"=c,C");c=a+b;C=A+B
print a/A,b/B

ऋषि को केवल अंतिम पंक्ति में आवश्यक है, जो आउटपुट का ख्याल रखता है। बाकी सब भी पायथन में काम करता है।

बदलें raw_input()साथ sys.argv[1]इनपुट एक संकेत के बजाय एक कमांड लाइन तर्क से पढ़ा है। इससे कैरेक्टर काउंट नहीं बदलता है। ( sysपहले आयात किए बिना पायथन में काम नहीं करता है ।)

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

यह मेरी मशीन पर एक सेकंड से भी कम समय में सभी उदाहरणों को सही ढंग से संसाधित करता है।

यहाँ एक ungolfed संस्करण है:

x,X = map(Integer,sys.argv[1].split('/'))
x = x/X
a = 0
c = b = 1
while c.denominator() < X:
    if c > x:
        b = c
    else:
        a = c
    c = ( a.numerator() + b.numerator() ) / ( a.denominator() + b.denominator() )
print a,b

मुझे पहले ही डर था कि मुझे इस इनाम के लिए कोई नया सबमिशन नहीं मिलेगा। अच्छा कार्य।
user2428118

अच्छी चाल के साथ exec!
xnor

एक ही जवाब के रूप में इनाम की अवधि के भीतर प्रस्तुत किया गया है, मैं आपको यह इनाम प्रदान कर रहा हूं। बधाई हो।
user2428118 19

मैंने सिर्फ एक उदाहरण में एक त्रुटि तय की । आप अपनी सबमिशन को सही करना चाह सकते हैं (भले ही आपको इसे सबमिट किए हुए आधा साल हो गया हो)।
user2428118

12

पायथन 2.7 - 138

x,y=n,d=map(int,raw_input().split('/'))
while y:x,y=y,x%y
def f(p,a=d):
 while(a*n+p)%d:a-=1
 print`(a*n+p)/d`+('/'+`a`)*(a>1),
f(-x);f(x)

मैंने स्पष्ट ब्रूट-फोर्स समाधान के साथ शुरुआत की, लेकिन मुझे एहसास हुआ कि चूंकि ओपी एक मिनट के भीतर छह अंकों के अंश और हर के साथ इंस्टेंस को हल करने में सक्षम होना चाहता था, इसलिए मुझे एक ट्रिलियन संभावनाओं की कोशिश करने की तुलना में बेहतर समाधान की आवश्यकता है। मुझे फेरी अनुक्रम के लिए विकिपीडिया पृष्ठ पर एक आसान सूत्र मिला: यदि a / b, c / d में से किसी एक में फ़ारेसी अनुक्रम हैं a/b<c/d, तो b*c-a*b=1। मेरे प्रोग्राम में f के अंदर का लूप इस तथ्य को गैर-कम किए गए नंबरों तक बढ़ाता है, gcd का उपयोग करते हुए, जिसे दूसरा लूप कैलकुलेट करता है।

मैंने पहले से ही इसे बहुत कठिन बना दिया है, लेकिन मुझे कोई सुझाव सुनना अच्छा लगेगा।

संपादन:

166-> 162: हटा दिया गया aऔर bबाहरी कार्यक्रम से। वे अनावश्यक थे।
162-> 155: str()-> ``
155-> 154: जोड़ा गया k
154-> 152: xफ़ंक्शन के अंदर से निकाला गया , इसे एक तर्क के रूप में पारित कर दिया।
152-> 150: aइसे एक तर्क के रूप में पारित करने के बजाय एक डिफ़ॉल्ट मान दिया ।
150-> 146: के आरंभीकरण को बदल दिया xऔर y
146-> 145: हटाया गया k
145-> 144: परिवर्तित ... और ... या ... से ((, ...) [...], जिससे एक स्थान की बचत होती है।
144-> 138: परिवर्तित ((..., ...) [...] से ... + ... * (...)। @ Mbomb007 को धन्यवाद।

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

2/5
1/3 1/2

1/2
0 1

2/4
1/3 2/3

179565/987657
170496/937775 128779/708320

12345678/87654321
12174209/86436891 11145405/79132382

दूसरे से अंतिम परीक्षण ने मेरे कंप्यूटर पर एक सेकंड के तहत लिया, जबकि अंतिम में लगभग 5-10 सेकंड लगे।


यह k=1शुद्ध दुष्टता है।
Evpok

1
@ ईवपोक: मैं काम करने के लिए k = y = n प्राप्त करने की कोशिश कर रहा था, लेकिन जाहिर है अगर आप किसी फ़ंक्शन के अंदर एक चर को संशोधित करते हैं, तो अजगर चाहता है कि यह स्थानीय हो। यह 4 वर्णों में एक स्थानीय चर प्राप्त करने का एकमात्र तरीका था। इसके अलावा, चूंकि अंश सकारात्मक और उचित है, हर 1 नहीं हो सकता है
isaacg

पायथन के साथ कमांड-लाइन तर्क आसान हैं, इसलिए उन्हें यहां निर्देश के अनुसार इनपुट के लिए उपयोग किया जाना चाहिए।
एलेक्स थॉर्नटन

1
" आप चुन सकते हैं कि क्या आप कमांड-लाइन तर्क (जैसे yourprogram.exe 2/5) के रूप में अंश प्राप्त करना चाहते हैं या किसी अन्य इनपुट के लिए संकेत दें ।"
इसहाक

6 वर्ण सहेजें:print`(a*n+p)/d`+('/'+`a`)*(a>1),
mbomb007

5

गणितज्ञ, 163 बाइट्स

{a,b}=FromDigits/@InputString[]~StringSplit~"/";r=Range[b-1];""<>Riffle[#~ToString~InputForm&/@(#@DeleteCases[#2[a/b*r]/r,a/b]&@@@{{Max,Floor},{Min,Ceiling}})," "]

यह उपयोगकर्ता इनपुट और स्ट्रिंग्स के रूप में इनपुट / आउटपुट आवश्यकता द्वारा गंभीर रूप से सीमित है। स्ट्रिंग्स से निपटना वास्तव में मैथेमेटिका में बोझिल है (कम से कम जब आप गोल्फ चाहते हैं)। Mathematica में इसका प्राकृतिक तरीका, (केवल पूर्णांकों और परिमेय का उपयोग करके) यह संभवत: मुझे आकार के 50% तक मिलेगा।

यह मेरी मशीन पर कुछ सेकंड में 6 अंकों की संख्या कर सकता है।

थोड़ा अधिक पठनीय (हालांकि वास्तव में अपढ़ नहीं):

{a, b} = FromDigits /@ InputString[]~StringSplit~"/";
r = Range[b - 1];
"" <> Riffle[#~ToString~
     InputForm & /@ (#[DeleteCases[#2[a/b*r]/r, a/b]] & @@@ {{Max, 
       Floor}, {Min, Ceiling}}), " "]

इसके मज़े के लिए, यह "प्राकृतिक तरीका", यानी एक फ़ंक्शन के रूप में, अंश और हर लेने वाले और दो तर्क को वापस करने के लिए, यह केवल 84 वर्ण है (इसलिए मेरा 50% अनुमान वास्तव में बहुत करीब था):

f[a_,b_]:=#@DeleteCases[#2[a/b*(r=Range[b-1])]/r,a/b]&@@@{{Max,Floor},{Min,Ceiling}}

3

जूलिया - 127 125 बाइट्स

मैंने लूप की आवश्यकता से बचने के लिए गणितीय दृष्टिकोण से यह संपर्क किया है, इसलिए यह कोड बड़े इनपुट के लिए काफी तेजी से चलता है (नोट: यदि a / b इनपुट है, तो Int64 के भीतर एक * b को फिट होना चाहिए (32 बिट सिस्टम पर Int32) , अन्यथा बकवास उत्तर उत्पन्न होते हैं - यदि कोई और बी दोनों Int32 में स्पष्ट हैं (32 बिट सिस्टम पर Int16), कोई समस्या नहीं है)।

अद्यतन: अब by, एक शुद्ध बचत 2 बाइट्स का उपयोग करके, div के लिए बैकस्लैश को अधिभारित करने की आवश्यकता नहीं है।

a,b=int(split(readline(),"/"));k=gcd(a,b);f=b-invmod(a÷k,b÷k);d=2b-f-b÷k;print(a*d÷b,d<2?" ":"/$d ",a*f÷b+1,"/$f"^(f>1))

Ungolfed:

a,b=int(split(readline(),"/")) # Read in STDIN in form a/b, convert to int
k=gcd(a,b)           # Get the greatest common denominator
f=b-invmod(a÷k,b÷k)  # Calculate the denominator of the next biggest fraction
d=2b-f-b÷k           # Calculate the denominator of the next smallest fraction
print(a*d÷b,d<2?" ":"/$d ",a*f÷b+1,"/$f"^(f>1)) # Calculate numerators and print

मूल विचार: सबसे बड़ा d और f खोजें जो b से कम है जो ad-bc = gcd (a, b) (अगला सबसे छोटा) और be-af = gcd (a, b) (अगला सबसे बड़ा) को संतुष्ट करता है, फिर c और e से गणना करें क्या आप वहां मौजूद हैं। परिणामी आउटपुट c / de / f है, जब तक कि d या f 1 न हो, उस स्थिति में / d या f को छोड़ दिया जाता है।

दिलचस्प है, इसका मतलब है कि कोड सकारात्मक अनुचित अंशों के लिए भी काम करता है, इसलिए जब तक इनपुट एक पूर्णांक नहीं है (अर्थात, जीसीडी (ए, बी) = ए)।

मेरे सिस्टम पर, 194857602/34512958303इनपुटिंग आउटपुट के लिए कोई उल्लेखनीय समय नहीं लेता है171085289/30302433084 23772313/4210525219


के साथ परीक्षण 55552/999999मुझे देता है -396/920632 486/936509
user2428118

@ user2428118 - क्या आप 32 बिट सिस्टम पर हैं (या 32 बिट जूलिया का उपयोग कर रहे हैं)? मैंने "int" का उपयोग किया है, जिसका अर्थ है कि 32 बिट सिस्टम पर, यह Int64 के बजाय Int32 का उपयोग करेगा। int32(55552*999999)देता है -282630400। मेरे लिए, उस परीक्षण के साथ, मुझे पता है 51143/920632 52025/936509- ध्यान दें कि हर एक समान हैं, और यह 52025-51143 = 486 - (- 396) है। मैं इस मुद्दे का उल्लेख करने के लिए एक नोट जोड़ूंगा।
ग्लेन ओ

यदि आप यह सुनिश्चित करना चाहते हैं कि कोड सभी Int64 आकार के इनपुट के लिए काम करेगा, तो आप "int" को "int128" से बदल सकते हैं। उस परिवर्तन के साथ, इनपुटिंग में 1234567891234567/2145768375829475878परिणाम आता है 869253326028691/1510825213275018197 365314565205876/634943162554457681। यह परिवर्तन सिर्फ 3 अतिरिक्त वर्ण जोड़ता है।
ग्लेन ओ

हां, मैं 32-बिट कंप्यूटर का उपयोग कर रहा हूं। मैं इसे 64-बिट मशीन पर कभी-कभी आज़माऊंगा जब मुझे इसके लिए समय मिल गया हो।
user2428118

64-बिट कंप्यूटर पर परीक्षण सही परिणाम देता है, इसलिए मैं इस उत्तर को स्वीकार कर रहा हूं।
user2428118

2

जावास्क्रिप्ट, 131

वसा तीर संकेतन और evalकॉल के साथ:

m=>{for(e=eval,n=e(m),i=p=0,q=1;++i</\d+$/.exec(m);)if(n*i>(f=n*i|0))g=f+1,p=f/i>e(p)?f+'/'+i:p,q=g/i<e(q)?g+'/'+i:q;return p+' '+q}

179565/987657तनाव परीक्षण लगभग में निष्पादित किया जाता है 35 सेकंड , Firefox पर एक बहुत क्रोम के बारे में अधिक (~ 6 मिनट)

तेजी से विधि और बिना evalऔर वसा तीर संकेतन

for(n=eval(m=prompt(a=i=p=0,b=c=d=q=1));++i<m.match(/\d+$/);)if(n*i>(f=n*i|0))g=f+1,p=f*c>i*a?(a=f)+'/'+(c=i):p,q=g*d<i*b?(b=g)+'/'+(d=i):q;alert(p+' '+q)

179565/987657तनाव परीक्षण लगभग 5 सेकंड में मार डाला गया है।

गोल्फ नहीं:

m=prompt(); //get input
a=0; c=1; //first fraction
b=1; d=1; //second fraction
n=eval(m); //evaluate input
for (i=1; i<m.match(/\d+$/); i++) { //loop from 1 to input denominator
  f=Math.floor(n*i);
  if (n*i > f) { //if fraction not equal to simplification of input
    g=f+1; // f/i and g/i are fractions closer to input
    if (f/i>a/c) a=f, c=i;
    if (g/i<b/d) b=g; d=i; 
  }
}
alert(a+'/'+c+' '+b+'/'+d); //output values handling 0 and 1 correctly

बहुत ... बहुत ... eval। EEK
जॉन ड्वोरक

3
साथ परीक्षण 2/6देता है 1/3 2/5, फिर भी 1/3नहीं है कम से कम लेकिन के बराबर 2/6
user2428118

@ user2428118 फिक्स्ड
माइकल एम।

इस उत्तर को इतनी जल्दी क्यों स्वीकार कर लिया गया है?
Evpok

1
@ user2428118: आप जानते हैं, आप समाधान स्वीकार करने से पहले कुछ दिनों की अनुमति दे सकते हैं। साथ ही, यह समाधान अब सबसे छोटा नहीं है।
इसहाक

2

पर्ल, 142 बाइट्स (सीपीएएन के बिना 155)

use bare A..Z;$/="/";N=<>;D=<>;F=N/D;K=G=1;for$H(1..D){J<F&&J>E?(E,I):J>F&&J<G?(G,K):()=(J=$_/H,"$_/$H")for(Z=int F*H)..Z+1}print I||0," $K\n"

या अगर CPAN मॉड्यूल को बंद कर दिया जाता है / 3-4 बार तेज कोड की आवश्यकता होती है:

$/="/";$N=<>;$D=<>;$F=$N/$D;$g=$G=1;for$d(1..$D){$f<$F&&$f>$E?($E,$e):$f>$F&&$f<$G?($G,$g):()=($f=$_/$d,"$_/$d")for($z=int$F*$d)..$z+1}print$e||0," $g\n"

पूर्व संस्करण मेरी मशीन पर 9.55 सेकंड, बाद वाला संस्करण 2.44 सेकंड लेता है।

कम अपठनीय:

($N, $D) = split(m[/], <>);
$F = $N / $D;
$G = 1;
foreach $d (1 .. $D) {
    $z = int $F * $d;
    foreach $_ ($z .. $z + 1) {
        $f = $_ / $d;
        ($f < $F && $f > $E ? ($E, $e) :
        ($f > $F && $f < $G ? ($G, $g) : ())) = ($f, "$_/$d");
    }
}
print $e || 0, ' ', $g || 1, "\n";
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.