ऑटो-सुपर-लॉगरिथम करो


18

एक सकारात्मक पूर्णांक को देखते हुए एन और एक नंबर एक , एन वें tetration की एक के रूप में परिभाषित किया गया है एक ^ ( एक ^ ( एक ^ (... ^ एक ))) है, जहां ^ घातांक (या शक्ति) को दर्शाता है और अभिव्यक्ति शामिल नंबर एक बिल्कुल n बार।

दूसरे शब्दों में, टेट्रेशन राइट-एसोसिएटिव इटेरेटेड एक्सपोनेंशन है। के लिए n = 4 और एक = 1.6 tetration 1,6 ^ (1,6 ^ (1,6 ^ 1,6)) है ≈ 3.5743।

के संबंध में tetration का प्रतिलोम समारोह n है सुपर लघुगणक । पिछले उदाहरण में, 4, "सुपर-बेस" 1.6 के साथ 3.5743 का सुपर-लॉगरिदम है।

चुनौती

एक धनात्मक पूर्णांक n को देखते हुए , x को खोजें जैसे कि n , सुपर-बेस x में स्वयं का सुपर-लघुगणक है । अर्थात्, x को ऐसे x ^ ( x ^ ( x ^ (... ^ x ))) में खोजें ( x के साथ n बार प्रदर्शित होने पर ) n को बराबर करें ।

नियम

कार्यक्रम या समारोह की अनुमति दी।

इनपुट और आउटपुट प्रारूप हमेशा की तरह लचीले होते हैं।

एल्गोरिथ्म को सैद्धांतिक रूप से सभी सकारात्मक पूर्णांकों के लिए काम करना चाहिए। व्यवहार में, इनपुट स्मृति, समय या डेटा-प्रकार प्रतिबंधों के कारण अधिकतम मूल्य तक सीमित हो सकता है। हालाँकि, कोड को 100कम से कम एक मिनट से कम के इनपुट के लिए काम करना चाहिए ।

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

सबसे छोटा कोड जीतता है।

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

1    ->  1
3    ->  1.635078
6    ->  1.568644
10   ->  1.508498
25   ->  1.458582
50   ->  1.448504
100  ->  1.445673

संदर्भ कार्यान्वयन

यहां मटलब / ऑक्टेव में एक संदर्भ कार्यान्वयन है ( आइडोन पर प्रयास करें )।

N = 10; % input
t = .0001:.0001:2; % range of possible values: [.0001 .0002 ... 2]
r = t;
for k = 2:N
    r = t.^r; % repeated exponentiation, element-wise
end
[~, ind] = min(abs(r-N)); % index of entry of r that is closest to N
result = t(ind);
disp(result)

इसके लिए N = 10देता है result = 1.5085

निम्नलिखित कोड चर-सटीक अंकगणित का उपयोग करते हुए आउटपुट परिशुद्धता का एक चेक है:

N = 10;
x = 1.5085; % result to be tested for that N. Add or subtract 1e-3 to see that
            % the obtained y is farther from N
s = num2str(x); % string representation
se = s;
for n = 2:N;
    se = [s '^(' se ')']; % build string that evaluates to iterated exponentiation
end
y = vpa(se, 1000) % evaluate with variable-precision arithmetic

यह देता है:

  • के लिए x = 1.5085:y = 10.00173...
  • के लिए x = 1.5085 + .001:y = 10.9075
  • इसके लिए x = 1.5085 - .001देता है y = 9.23248

तो सटीक के 1.5085साथ एक वैध समाधान है .001


संबंधित । अंतर यह है कि सुपर-लॉगरिदम का (सुपर-) आधार यहां तय नहीं है, और परिणाम सामान्य रूप में पूर्णांक नहीं है।
लुइस मेंडो

ऐसा लगता है कि फ़ंक्शन त्वरित रूप से परिवर्तित होता है। अगर हमारा एल्गोरिथ्म बस एक वक्र फिट है जो 0.001 के भीतर है, तो क्या यह सभी सैद्धांतिक पूर्णांक के लिए सैद्धांतिक रूप से काम करता है?
xnor


@ केविनक्रूजसेन I में बाइनरी सर्च के आधार पर मतलाब में एक संदर्भ कार्यान्वयन है जो यथोचित तेज़ है। अगर यह उपयोगी हो तो मैं इसे पोस्ट कर सकता हूं
लुइस मेंडो

1
क्या अनंत के xरूप में अभिसरण होता है n?
mbomb007

जवाबों:


3

दिल्लोग एपीएल , 33 25 बाइट्स

⎕IO←0कई प्रणालियों पर डिफ़ॉल्ट की आवश्यकता है।

⌈/⎕(⊢×⊣≥(*/⍴)¨)(1+⍳÷⊢)1E4

सैद्धांतिक रूप से सभी पूर्णांकों के लिए गणना करता है, लेकिन व्यावहारिक रूप से केवल बहुत छोटे तक सीमित है।

TryAPL ऑनलाइन!


क्या यह इनपुट 100 पर पर्याप्त तेजी से काम करता है?
ग्रेग मार्टिन

@GregMartin पर्याप्त मेमोरी नहीं है।
अड्म

10

हास्केल, 55 54 52 बाइट्स

s n=[x|x<-[2,1.9999..],n>iterate(x**)1!!floor n]!!0

उपयोग:

> s 100
1.445600000000061

1 बाइट के लिए @nimi को धन्यवाद!
2 के लिए @xnor को धन्यवाद!


1
[ ]!!0इसके बजाय head[ ]एक बाइट बचाता है
nimi

1
s n=[x|x<-[2,1.9999..],n>iterate(x**)1!!n]!!0यदि आप हास्केल को इसके प्रकारों को स्वीकार करने के लिए कम कर सकते हैं।
xnor

@xnor जब मैंने इसे लिखा था तब मैंने इसे इट्रैट के साथ बजाया था, लेकिन किसी तरह यह समय के साथ लंबा हो गया
BlackCap

6

जावास्क्रिप्ट, ईएस 6: 77 बाइट्स / ईएस 7: 57 53 बाइट्स

ES6

n=>eval("for(x=n,s='x';--x;s=`Math.pow(x,${s})`);for(x=2;eval(s)>n;)x-=.001")

ES7

**DanTheMan द्वारा सुझाए अनुसार उपयोग करना :

n=>eval("for(x=2;eval('x**'.repeat(n)+1)>n;)x-=.001")

उदाहरण

let f =
n=>eval("for(x=n,s='x';--x;s=`Math.pow(x,${s})`);for(x=2;eval(s)>n;)x-=.001")

console.log(f(25));


यदि आप ES7 का उपयोग करते हैं, तो आप **इसके स्थान पर उपयोग कर सकते हैं Math.pow
डैनमैन मैन

4

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

लगभग 20% बचत के लिए मर्फी के लिए धन्यवाद!

1//.x_:>x+.001/;Nest[x^#&,1,#]<#&

Nest[x^#&,1,n]x का nth टेट्रेशन पैदा करता है। तो Nest[x^#&,1,#]<#परीक्षण करता है कि क्या x के इनपुट (इनपुट) वें tetration से कम है (इनपुट)। हम बस x = 1 से शुरू करते हैं और 0.001 तक बार-बार जोड़ते हैं जब तक टेट्रेशन बहुत बड़ा नहीं होता है, तब अंतिम x मान का उत्पादन करें (इसलिए उत्तर सटीक मान से बड़ा होने की गारंटी है, लेकिन 0.001 के भीतर)।

जैसा कि मैं धीरे-धीरे सीख रहा हूं: //.x_:>y/;zया //.x_/;z:>y"किसी भी चीज़ के लिए देखो जो टेम्पलेट x से मेल खाता है, लेकिन केवल ऐसी चीजें हैं जिनके लिए परीक्षण z वापस लौटता है और फिर नियम y द्वारा x पर काम करता है; बार-बार जब तक कुछ भी नहीं बदलता है"। यहां टेम्प्लेट x_सिर्फ "किसी भी संख्या को मैं देख रहा हूं", हालांकि अन्य संदर्भों में इसे और अधिक विवश किया जा सकता है।

जब इनपुट कम से कम 45 होता है, तो टेट्रेशन इतनी तेजी से बढ़ता है कि अंतिम चरण में अतिप्रवाह त्रुटि का कारण बनता है; लेकिन x का मान अभी भी अद्यतन है और सही ढंग से आउटपुट है। चरण-आकार को 0.001 से 0.0001 तक कम करना इस समस्या को 112 तक के इनपुट के लिए ठीक करता है, और बूट के बारे में अधिक सटीक उत्तर देता है (और अभी भी लगभग एक चौथाई सेकंड में तेजी से चलता है)। लेकिन यह एक अतिरिक्त बाइट है, इसलिए भूल जाओ!

मूल संस्करण:

x=1;(While[Nest[x^#&,1,#]<#,x+=.001];x)&

इसे थोड़ा गुदगुदाया:1//.x_:>x+.001/;Nest[x^#&,1,#]<#&
मर्फी

@ मर्फी: महान! मैं शपथ लेता हूँ कि मैं अभी तक उस बिंदु पर पहुँच जाऊँगा जहाँ मैं //.बिना किसी सहायता के उपयोग कर सकता हूँ :)
ग्रेग मार्टिन

4

जे, ३ ९ ३१ २, बाइट्स

(>./@(]*[>^/@#"0)1+i.%])&1e4

संदर्भ कार्यान्वयन के आधार पर। यह केवल तीन दशमलव स्थानों के लिए सटीक है।

@ Adám के समाधान से विधि का उपयोग करके 8 बाइट्स सहेजे गए ।

प्रयोग

एकाधिक इनपुट / आउटपुट को प्रारूपित करने के लिए उपयोग की जाने वाली अतिरिक्त कमांड।

   f =: (>./@(]*[>^/@#"0)1+i.%])&1e4
   (,.f"0) 1 3 6 10 25 50 100
  1      0
  3  1.635
  6 1.5686
 10 1.5084
 25 1.4585
 50 1.4485
100 1.4456
   f 1000
1.4446

व्याख्या

(>./@(]*[>^/@#"0)1+i.%])&1e4  Input: n
                         1e4  The constant 10000
(                      )      Operate on n (LHS) and 10000 (RHS)
                   i.           The range [0, 10000)
                      ]         Get (RHS) 10000
                     %          Divide each in the range by 10000
                 1+             Add 1 to each
     (          )               Operate on n (LHS) and the range (RHS)
             #"0                  For each in the range, create a list of n copies
          ^/@                     Reduce each list of copies using exponentation
                                  J parses from right-to-left which makes this
                                  equivalent to the tetration
        [                         Get n
         >                        Test if each value is less than n
      ]                           Get the initial range
       *                          Multiply elementwise
 >./@                           Reduce using max and return

4

पायथन, 184 बाइट्स

def s(n):
 def j(b,i):
  if i<0.1**12:
   return b
  m = b+i
  try:
   v = reduce(lambda a,b:b**a,[m]*n)
  except:
   v = n+1
  return j(m,i/2) if v<n else j(b,i/2)
 return j(1.0,0.5)

टेस्ट आउटपुट (वास्तविक प्रिंट स्टेटमेंट को छोड़ना):

   s(1) 1.0
   s(3) 1.63507847464
   s(6) 1.5686440646
  s(10) 1.50849792026
  s(25) 1.45858186605
  s(50) 1.44850389566
 s(100) 1.44567285047


यह s(1000000)बहुत जल्दी गणना करता है
mbomb007

3

रैकेट 187 बाइट्स

(define(f x n)(define o 1)(for((i n))(set! o(expt x o)))o)
(define(ur y(l 0.1)(u 10))(define t(/(+ l u)2))(define o(f t y))
(cond[(<(abs(- o y)) 0.1)t][(> o y)(ur y l t)][else(ur y t u)]))

परिक्षण:

(ur 1)
(ur 3)
(ur 6)
(ur 10)
(ur 25)
(ur 50)
(ur 100)

आउटपुट:

1.028125
1.6275390625
1.5695312499999998
1.5085021972656247
1.4585809230804445
1.4485038772225378
1.4456728475168346

विस्तृत संस्करण:

(define (f x n)
  (define out 1)
  (for((i n))
    (set! out(expt x out)))
  out)

(define (uniroot y (lower 0.1) (upper 10))
  (define trying (/ (+ lower upper) 2))
  (define out (f trying y))
  (cond
    [(<(abs(- out y)) 0.1)
     trying]
    [(> out y)
     (uniroot y lower trying)]
    [else
      (uniroot y trying upper)]))

2

पर्ल 6 , 42 बाइट्स

{(0,.00012).min:{abs $_-[**] $^r xx$_}}

(उदाहरण मैटलैब कोड का अनुवाद)

परीक्षा:

#! /usr/bin/env perl6
use v6.c;
use Test;

my &code = {(0,.00012).min:{abs $_-[**] $^r xx$_}}

my @tests = (
  1   => 1,
  3   => 1.635078,
  6   => 1.568644,
  10  => 1.508498,
  25  => 1.458582,
  50  => 1.448504,
  100 => 1.445673,
);

plan +@tests + 1;

my $start-time = now;

for @tests -> $_ ( :key($input), :value($expected) ) {
  my $result = code $input;
  is-approx $result, $expected, "$result ≅ $expected", :abs-tol(0.001)
}

my $finish-time = now;
my $total-time = $finish-time - $start-time;
cmp-ok $total-time, &[<], 60, "$total-time.fmt('%.3f') is less than a minute";
1..8
ok 1 - 1  1
ok 2 - 1.6351  1.635078
ok 3 - 1.5686  1.568644
ok 4 - 1.5085  1.508498
ok 5 - 1.4586  1.458582
ok 6 - 1.4485  1.448504
ok 7 - 1.4456  1.445673
ok 8 - 53.302 seconds is less than a minute


1

Axiom 587 बाइट्स

l(a,b)==(local i;i:=1;r:=a;repeat(if i>=b then break;r:=a^r;i:=i+1);r);g(q,n)==(local r,y,y1,y2,t,v,e,d,i;n<=0 or n>1000 or q>1000 or q<0 => 0;e:=1/(10**(digits()-3));v:=0.01; d:=0.01;repeat(if l(v,n)>=q then break;v:=v+d;if v>=1 and n>25 then d:=0.001;if v>=1.4 and n>40 then d:=0.0001;if v>=1.44 and n>80 then d:=0.00001;if v>=1.445 and n>85 then d:=0.000001);if l(v-d,n)>q then y1:=0.0 else y1:=v-d;y2:=v;y:=l(v,n);i:=1;if abs(y-q)>e then repeat(t:=(y2-y1)/2.0;v:=y1+t;y:=l(v,n);i:=i+1;if i>100 then break;if t<=e then break;if y<q then y1:=v else y2:=v);if i>100 then output "#i#";v)

कम गोल्फ वाले + नंबर

l(a,b)==
  local i
  i:=1;r:=a;repeat(if i>=b then break;r:=a^r;i:=i+1)
  r
g(q,n)==
 local r, y, y1,y2,t,v,e,d, i
 n<=0 or n>1000 or q>1000 or q<0 => 0  
 e:=1/(10**(digits()-3))
 v:=0.01; d:=0.01  
 repeat  --cerco dove vi e' il punto di cambiamento di segno di l(v,n)-q
    if l(v,n)>=q then break
    v:=v+d 
    if v>=1     and n>25 then d:=0.001
    if v>=1.4   and n>40 then d:=0.0001
    if v>=1.44  and n>80 then d:=0.00001
    if v>=1.445 and n>85 then d:=0.000001
 if l(v-d,n)>q then y1:=0.0
 else               y1:=v-d 
 y2:=v; y:=l(v,n); i:=1  -- applico il metodo della ricerca binaria
 if abs(y-q)>e then      -- con la variabile i di sicurezza
    repeat 
       t:=(y2-y1)/2.0; v:=y1+t; y:=l(v,n)
       i:=i+1
       if i>100 then break
       if t<=e  then break 
       if  y<q  then y1:=v
       else          y2:=v
 if i>100 then output "#i#"
 v

(3) -> [g(1,1), g(3,3), g(6,6), g(10,10), g(25,25), g(50,50), g(100,100)]
   Compiling function l with type (Float,PositiveInteger) -> Float
   Compiling function g with type (PositiveInteger,PositiveInteger) ->
      Float

   (3)
   [1.0000000000 000000001, 1.6350784746 363752387, 1.5686440646 047324687,
    1.5084979202 595960768, 1.4585818660 492876919, 1.4485038956 661040907,
    1.4456728504 738144738]
                                                             Type: List Float

1

आम लिस्प, 207 बाइट्स

(defun superlog(n)(let((a 1d0)(i 0.5))(loop until(< i 1d-12)do(let((v(or(ignore-errors(reduce #'expt(loop for q below n collect(+ a i)):from-end t))(1+ n))))(when(< v n)(setq a (+ a i)))(setq i(/ i 2)))) a))

के reduceसाथ प्रयोग करने :from-end tसे एक "प्रतिक्षेपक घातांक" मध्यवर्ती लैम्ब्डा करने की आवश्यकता से बचा जाता है (मूल रूप से (lambda (x y) (expt y x)), 14 बाइट्स की बचत, (12, यदि आप हटाने योग्य रिक्त स्थान को हटा दें)।

हमें अभी भी फ़्लोट ओवरफ़्लो को संभालने की आवश्यकता है, लेकिन यदि कोई त्रुटि हुई तो एक ignore-errorsफ़ॉर्म वापस आ nilजाता है, इसलिए हम orडिफ़ॉल्ट मान प्रदान करने के लिए उपयोग कर सकते हैं ।

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