자동 슈퍼 로그를 수행


18

양수 주어 N 및 숫자 상기 N 번째 테트 레이션A는 로서 정의된다 ^ ( ^ ( ^ (... ^ ))), 여기서 ^는 지수 (또는 전력)을 나타낸다 및식이 포함 숫자 정확히 n 번입니다.

다시 말해, tetration은 right-associative 반복 지수화입니다. 들면 N = 4 = 1.6 테트 레이션 1.6 ^ (1.6 ^ (1.6 ^ 1.6))이다 ≈ 3.5743.

n에 대한 정션의 역함수 는 수퍼 로그 입니다. 이전 예에서 4는 "super-base"1.6이 포함 된 3.5743의 수퍼 로그입니다.

도전

양의 정수를 감안할 때 N , 찾아 X 하도록 n은 슈퍼베이스에서 자체의 슈퍼 로그 인 x가 . 즉, 발견 X 되도록 X ^ ( X ^ ( X ^ (... ^ x가 ))) (와 X가 나타나는 N 회)와 동일 없음 .

규칙

프로그램 또는 기능이 허용됩니다.

입력 및 출력 형식은 평소처럼 유연합니다.

알고리즘은 이론적으로 모든 양의 정수에 대해 작동해야합니다. 실제로, 입력은 메모리, 시간 또는 데이터 유형 제한으로 인해 최대 값으로 제한 될 수 있습니다. 그러나 코드는 100최소 1 분 이내에 입력에 대해 작동해야합니다 .

알고리즘은 이론적으로 결과를 0.001정밀하게 제공해야합니다 . 실제로, 수치 계산에서 누적 오차로 인해 출력 정밀도가 떨어질 수 있습니다. 그러나 0.001표시된 테스트 사례 에 대해 출력이 정확해야합니다 .

가장 짧은 코드가 승리합니다.

테스트 사례

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

참조 구현

Matlab / Octave 의 참조 구현 은 다음과 같습니다 ( Ideone 에서 시도하십시오 ).

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정밀도.


관련 . 차이점은 여기서 수퍼 로그의 (수퍼)베이스는 고정되어 있지 않으며 결과는 일반적으로 정수가 아닙니다.
Luis Mendo

함수가 다소 빨리 수렴하는 것처럼 보입니다. 우리의 알고리즘이 0.001 이내의 곡선 맞춤이라면 이론적으로 모든 양의 정수에 대해 작동하는 것으로 간주됩니까?
xnor

2
wolframalpha는 이미 테스트 사례 6에 문제가 있습니다. " 표준 계산 시간이 초과되었습니다 ... "
Kevin Cruijssen

@KevinCruijssen 나는 이진 검색을 기반으로 Matlab에 참조 구현이 있는데 이는 상당히 빠릅니다. 도움이된다면 게시 할 수 있습니다
Luis Mendo

1
음주자 x로 수렴 n무한대에 가까워?
mbomb007

답변:


3

Dyalog APL , 33 25 바이트

⎕IO←0많은 시스템에서 기본값이 필요 합니다.

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

이론적으로 모든 정수에 대해 계산하지만 실제로 매우 작은 정수로만 제한됩니다.

TryAPL 온라인!


입력 100에서 충분히 빠르게 작동합니까?
Greg Martin

@GregMartin 메모리가 부족합니다.
Adám

10

하스켈, 55 54 52 바이트

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

용법:

> s 100
1.445600000000061

1 바이트의 @nimi에게 감사드립니다!
@xnor에게 2를 주셔서 감사합니다!


1
[ ]!!0head[ ]바이트 를 절약하는 대신
nimi

1
s n=[x|x<-[2,1.9999..],n>iterate(x**)1!!n]!!0Haskell이 유형을 받아 들일 수 있다면 더 짧을 것입니다.
xnor

@xnor 실제로 작성했을 때 반복 작업을했지만 시간이 더 길어졌습니다
BlackCap

6

자바 스크립트, ES6 : 77 바이트 / ES7 : 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.
DanTheMan

4

Mathematica, 40 33 바이트

거의 20 % 절약 된 머피 덕분입니다!

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

Nest[x^#&,1,n]x의 n 번째 tetration을 생성합니다. 따라서 Nest[x^#&,1,#]<#x의 (입력) 네 번째 테트 레이션이 (입력)보다 작은 지 테스트합니다. x = 1에서 시작하여 tetration이 너무 클 때까지 0.001을 반복해서 추가 한 다음 마지막 x 값을 출력합니다 (따라서 정답은 0.001 이내로 정확합니다).

느리게 학습하면서 : //.x_:>y/;z또는 //.x_/;z:>y"템플릿 x와 일치하는 것이지만 테스트 z가 true를 반환하는 것만 찾은 다음 규칙 y에 의해 x에서 작동합니다. x_다른 상황 에서는 템플릿 이 더 제한 될 수 있지만 여기서는 템플릿 이 "모든 숫자"입니다.

입력이 45 이상인 경우 테트라 션이 너무 빠르게 증가하여 마지막 단계에서 오버플로 오류가 발생합니다. 그러나 x 값은 여전히 ​​업데이트되어 올바르게 출력됩니다. 스텝 크기를 0.001에서 0.0001로 줄이면 최대 112 개의 입력에 대해이 문제가 해결되고 부팅에 대한보다 정확한 응답을 제공합니다 (약 1/4 초 안에 빠르게 실행 됨). 그러나 그것은 여분의 바이트이므로 잊지 마십시오!

원본 버전 :

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

약간 골프를 쳤다 :1//.x_:>x+.001/;Nest[x^#&,1,#]<#&
murphy

@ 머피 : 좋아! 나는 맹세하지만 난 아직 //.도움없이 사용할 수있는 지점에 도달 :)
그렉 마틴

4

J, 39 31 28 바이트

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

참조 구현을 기반으로합니다. 소수점 이하 세 자리까지만 정확합니다.

@ Adám 's solution 의 방법을 사용하여 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$_}}

(예 : Matlab 코드 번역)

테스트:

#! /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

PHP, 103 바이트

$z=2;while($z-$a>9**-9){for($r=$s=($a+$z)/2,$i=0;++$i<$n=$argv[1];)$r=$s**$r;$r<$n?$a=$s:$z=$s;}echo$s;

1

공리 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))

reducewith를 사용 :from-end t하면 "반전 지수화"중간 람다 (기본적으로 (lambda (x y) (expt y x))14 바이트 (이동식 공간을 제거하는 경우 12) 절약) 를 수행 할 필요가 없습니다 .

여전히 float overflow를 처리해야하지만 오류가 발생하면 ignore-errors폼이 반환 nil되므로 or기본값을 제공하는 데 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.