Ackermann işlevi


35

Ackermann işlevi, ilkel özyinelemeli olmayan, toplam, hesaplanabilir bir işlevin en basit örneklerinden biri olması nedeniyle dikkate değerdir.

A(m,n)İki negatif olmayan tamsayı alma tanımını kullanacağız.

A(0,n) = n+1
A(m,0) = A(m-1,1)
A(m,n) = A(m-1,A(m,n-1))

Uygulayabilirsiniz

  • giriş olarak iki tam sayı alan, bir tam sayı döndüren adlandırılmış veya adsız bir işlev veya
  • STDIN'de iki satır veya yeni satırla ayrılmış tam sayı alan ve STDOUT'a bir sonuç yazdıran bir program.

Varsa, bir kütüphaneden Ackermann işlevini ya da hiperxponentiation işlevini kullanamazsınız, ancak başka herhangi bir kütüphaneden başka bir işlev kullanabilirsiniz. Düzenli üstelleştirmeye izin verilir.

İşleviniz A(m,n), m ≤ 3 ve n ≤ 10 değerlerini bir dakikadan daha kısa bir sürede bulabilmelidir . En azından diğer girdilerde teorik olarak sonlandırılmalıdır: sonsuz yığın alanı, yerel bir Bigint tipi ve keyfi olarak uzun bir süre için, cevabı geri getirecektir. Düzenleme: Diliniz çok kısıtlayıcı olan varsayılan bir özyineleme derinliğine sahipse, bunu karakter maliyeti olmadan yeniden yapılandırabilirsiniz.

En kısa sayıda karakter içeren gönderim kazanır.

İşte cevabınızı kontrol etmek için bazı değerler:

  A  | n=0     1     2     3     4     5     6     7     8     9    10
-----+-----------------------------------------------------------------
 m=0 |   1     2     3     4     5     6     7     8     9    10    11
   1 |   2     3     4     5     6     7     8     9    10    11    12
   2 |   3     5     7     9    11    13    15    17    19    21    23
   3 |   5    13    29    61   125   253   509  1021  2045  4093  8189
   4 |  13 65533   big   really big...

15
Bu daha önce nasıl istenmedi?
Calvin'in Hobileri


22
Aşağı oy verme, çünkü burada zorluk yok. Açıkça cevap - sadece işlevini tam olarak tanımına göre saf bir şekilde uygulamak - her zaman en iyi cevap olacaktır. Yani soru sadece "Ackermann'ın işlevinin açık ifadesinde hangi dilde en az sayıda karakter var?" Asıl kazanan programlama dilidir, programdaki açık programı yazan kişi değil.
David Richerby

1
Dilimin özyineleme sınırı, A(3,8)diğerlerinin yaptığı gibi naif bir şekilde hesaplama yapmak için çok düşükse ne olur? Özyinelemesiz bir çözüm bulmak zorunda mıyım, yoksa bu durumlarda sadece "sonsuz yığın alanı üstlenebilir" mi? Oldukça eminim, bir dakika içinde sona erecek.
Martin Ender

5
@DavidRicherby "En açık cevap [...] her zaman en iyi cevap olacak." Bu tüm diller için doğru değildir. Sadece anadilimde bir örnek olduğu için biraz kirli hissediyorum, ancak Ackermann'ı ifade etmenin birçok yolu var ve bazı dillerde bu gerçeği kullanarak tasarruf edinebilirsiniz. Bu benim niyetimdi.
algoritmshark

Yanıtlar:


7

Pyth , 19

DaGHR?atG?aGtHH1GhH

aAckermann işlevi olarak çalışan tanımlar . Bunun, hesaplamak için bugüne kadar izin verilen resmi pyth derleyicisinden daha yüksek bir özyineleme derinliği gerektirdiğini unutmayın.a 3 10 ben yineleme derinliğini arttı yüzden. Bu dilde değil, sadece derleyicide bir değişiklik değildir.

Ölçek:

$ time pyth -c "DaGHR?atG?aGtHH1GhH           ;a 3 10"
8189

real    0m0.092s
user    0m0.088s
sys     0m0.000s

Açıklama:

DaGH                     def a(G,H):
    R                    return
    ?          G                (if G:
     atG                              (a(G-1,
        ?    H                               (if H:
         aGtH                                      a(G,H-1)
              1                               else:1)
                hH               else:H+1)

Temel olarak, önce GH + 1'in tekrarlanıp tekrarlanmamasının gerçeğe uygun değerine şart koşar. Eğer özyinelemeli ise, ilk argüman her zaman G-1'dir ve ikinci argüman olarak Hmı yoksa a(G,H-1)ikinci argüman olarak mı kullanılacağının gerçeğe uygunluğunu şart koşar 1.


Modern Pyth'te (bunun, bu zorluğun ardından eklendiğini varsayıyorum) DaGHR, Mve ' aye giderek daha az değişebileceğini düşünüyorum g. ( ?Değişim için savların sırası değişti mi?)
Lynn,

@Mauris Evet, Myerine kullanabilirsiniz ve evet, ?argüman sırası değişti. Şimdi şart, doğru, yanlış. Doğru, şart, yanlıştı.
isaacg

@Lynn Fun Pyth tarihinin gerçekleri: Bu soru aslında Pyth ile ilgili iki şeyi değiştirmeyi (en azından) etkiledi: özyineleme sınırı ve değişmeM !
FryAmTheEggman

23

Haskell, 35

0%n=1+n
m%n=iterate((m-1)%)1!!(n+1)

bu operatör fonksiyonunu tanımlar %.

Bu fark bu işler m%n(burada aSıfır dışındaki için ackerman fonksiyonudur) molduğu (m-1)%uygulandığı n+1kez 1. örneğin, 3%2olarak tanımlanır 2%(3%1)olan 2%(2%(3%0))ve bu2%(2%(2%1))


çok kötü öncelikli olmak 0%nyerine kullanamamn+1
gururlu haskeller


vay, bu çok uzun zamandır yanlış oldu ve kendim de dahil hiç kimse fark etmedi mi? iyi iş. bu yüzden yanlış bir cevap verdi, sanırım yanlış, cevabın ilk versiyonunu kopyaladım, belki de yanlışlıkla ya da çalıştığını düşündüm.
Gururlu haskeller

12

GolfScript (30)

{1$1>{1\){1$(\A}*\;}{+)}if}:A;

Çevrimiçi demo

1>(Hangi özel durumlarda A(1, n)) olmadan hesaplanması 9 dakika sürerA(3, 10) üzerinde test ettiğim bilgisayarda . Bu özel durumda, çevrimiçi demonun 10 saniyeden daha kısa sürmesi yeterince hızlı.

Bunun , tanımın naif bir çevirisi olmadığını unutmayın . Özyineleme derinliği ile sınırlıdır.m .

teşrih

{             # Function boilerplate
  1$          # Get a copy of m: stack holds m n m
  1>{         # (Optimisation): if m is greater than 1
    1         #   Take this as the value of A(m, -1)
    \){       #   Repeat n+1 times:
              #     Stack: m A(m, i-1)
      1$(\    #     Stack: m m-1 A(m, i-1)
      A       #     Stack: m A(m, i)
    }*
    \;        #   Lose that unwanted copy of m
  }{          # Else
    +)        #   A(m in {0, 1}, n) = m + n + 1
  }if
}:A;          # Function boilerplate

CJam’da buna ihtiyacınız yok 1>. Kaldırma işleminden sonra (ve değiştirdikten ifsonra ?), hesaplama 3 10 Açevrimiçi tercümanla 110 saniye ve Java tercümanla altı saniye sürer.
Dennis,

7

İkili lambda hesabı , 54 bit = 6.75 bayt

HexDump:

00000000: 1607 2d88 072f 68                        ..-../h

İkili:

000101100000011100101101100010000000011100101111011010

Bu λ m . m,gr . λ n . g ( n- g 1)) (λ n . λ f . λ x . f ( n f x )), tüm sayılar olarak temsil edilir Church numaraları .


6

JavaScript, ES6, 41 34 bayt

f=(m,n)=>m?f(m-1,!n||f(m,n-1)):n+1

Bunu en son Firefox Konsolunda çalıştırın f; farklı mve nbenzeri değerlerle çağırabileceğiniz bir işlev oluşturur.

f(3,2) // returns 29

VEYA

en son Firefox'ta aşağıdaki kodu deneyin

f=(m,n)=>m?f(m-1,!n||f(m,n-1)):n+1

B.onclick=_=>alert(f(+M.value, +N.value))
#M,#N{max-width:15px;border: 1px solid;border-width:0 0 1px 0}
<div>f(<input id=M />,<input id=N />)</div><br><button id=B>Evaluate</button>


Bunu Chrome'da 0,1 ile test etmek sonuç vermez.
Nzall

3
Pl oku, bu sadece ES6 nedeniyle en son Firefox'ta çalışıyor
Optimizer

Vay ... hepsi 34 byte olmak üzere 4 pratik JS çözümümüz var. Bunu daha önce hiç görmedim.
ETHProductions,

6

Python 2.7.8 - 80, 54, 48, 46 45

A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n

(Xnor'a kredi!)

Daha okunabilir, ancak 1 karakter daha:

A=lambda m,n:n+(m<1or A(m-1,n<1or A(m,n-1))-n)

sys.setrecursionlimit(10000)Sonuç almak için ayarlamam gerektiğinden değil A(3,10). Mantıksal endeksleme kullanarak daha fazla golf oynamak, çarpıcı şekilde artan özyinelemenin derinliği nedeniyle işe yaramadı.


Üzerinde bir sözdizimi hatası alıyorum 1else. Başlangıç ​​mektubu eayrıştırıcı için sorun yaratır, çünkü sayılar şöyle yazılabilir 1e3.
xnor

Geçiş yapan birkaç karakter kaydedildi and/or:A=lambda m,n:m and A(m-1,n<1or A(m,n-1))or-~n
xnor

@xnor: Bahşiş için teşekkürler! Ayrıştırma sorunu sorunu için bu tartışmaya bakın . Python 2.7.8 kabul ediyor 1else, diğer sürümlerin çoğu kabul etmiyor.
Falko

İşaretçi için teşekkür ederiz 1else; burada ve muhtemelen başka yerlerde bir kömürü sıkmamı sağlıyor . Ama kahretsin, versiyona özgü! Python 2.7.4 buna izin vermiyor. 2.7.8 olan bir çevrimiçi sürüm mü kullanıyorsunuz yoksa indirmek zorunda mıyım?
xnor

@xnor: Bu bir çevrimdışı yükleme. Örneğin, ideone.com da ayrıştıramadı 1else.
Falko

6

J - 26 karakter

($:^:(<:@[`]`1:)^:(0<[)>:)

Ackermann'ın alternatif, daha işlevsel bir tanımı var:

Ack 0 n = n+1
Ack m n = Iter (Ack (m-1)) n
Iter f 0 = f 1
Iter f n = f (Iter f (n-1))

Böylece olur IterJ geçen bir yol olduğundan, J yazma çok kolaydır m-1için Ackve aynı zamanda bir başlangıç değerini belirlemek için Iterpatlama Açıklaması 1. olması:

(                      >:)  NB. increment n
                ^:(0<[)     NB. if m=0, do nothing to n+1; else:
   ^:                       NB. iterate...
($:                      )  NB.   self ($: is recursion)
     (<:@[     )            NB.   with left arg m-1
          `]                NB.   n+1 times
            `1:             NB.   starting on 1

Bu, J'nin ^:çürük hali olarak adlandırdığı şeye dayanır - temelde zımni (noktasuz) bir şekilde tüm sınırlar üzerinde daha fazla kontrol sahibi olmanın bir yolu.

REPL'de:

   3 ($:^:(<:@[`]`1:)^:(0<[)>:) 3
61
   ack =: ($:^:(<:@[`]`1:)^:(0<[)>:)
   (i.4) ack"0 table (i.11)
+-----+------------------------------------------+
|ack"0|0  1  2  3   4   5   6    7    8    9   10|
+-----+------------------------------------------+
|0    |1  2  3  4   5   6   7    8    9   10   11|
|1    |2  3  4  5   6   7   8    9   10   11   12|
|2    |3  5  7  9  11  13  15   17   19   21   23|
|3    |5 13 29 61 125 253 509 1021 2045 4093 8189|
+-----+------------------------------------------+
   6!:2 '3 ($:^:(<:@[`]`1:)^:(0<[)>:) 10'  NB. snugly fits in a minute
58.5831

Tabloya ackkoymak için ismimizle tanımlamamız gerekiyor , çünkü $:korkunç, çirkin bir canavar ve onu anlamaya çalışan herhangi birisine çarpıyor. Öz, kendisini içeren en büyük fiil cümlesi olarak tanımlandığı öz-referanstır. tablebir zarftır ve eğer şansı verirseniz, fiil cümlesinin bir parçası olmayı çok istersiniz, bu yüzden $:kullanmak için adlandırılmış bir tanımda tuzağa düşmeniz gerekir.


Düzenleme: 24 karakter?

Yıllar sonra iki karakterden daha kısa bir çözüm buldum.

(0&<~(<:@#~$:/@,1:^:)>:)

Yine de çok daha yavaş: 3 ack 8makinemde bir dakikadan fazla zaman alıyor. Bunun nedeni (1) /yineleme yerine bir kat kullanıyorum, bu yüzden J muhtemelen normalden daha fazla şey hatırlamalıdır, ve (2) 0&<~aynı hesaplamayı yaparken (0<[)gerçekte idam edilir.n+1 çağırırken tekrarlayan adımı atmadan önce zamanlarım ack n - 0&<olur idempotent olmak, bu yüzden hesaplamayı mahvetmez, ama nhızlı ackbüyür ve özyinelemelidir.

Daha güçlü bir makinenin yeni kodu bir dakika içinde zorlayabileceğinden şüpheliyim, çünkü bu eski kodun bulabileceği bir bilgisayar. 3 ack 10 15 saniyeden kısa sürede .


5

C - 41 bayt

Hiçbir şey - küçük limitler, fonksiyon tanımını saf bir şekilde takip ederek gerekli tüm değerlerin 1 saniyeden daha kısa bir sürede hesaplanabileceği anlamına geliyor.

A(m,n){return!m?n+1:A(m-1,n?A(m,n-1):1);}


int main()
{
    int m,n;
    for(m = 0; m <= 3; m++)
    for(n = 0; n <= 10; n++)
    printf("%d %d %d\n", m,n,A(m,n));
    return 0;
}

5

Javascript ES6 (34)

a=(m,n)=>m?a(m-1,n?a(m,n-1):1):n+1

Uygulama:

a=(m,n)=>m?a(m-1,n?a(m,n-1):1):n+1
td[colspan="2"] input{width: 100%;}
<table><tbody><tr><td>m=</td><td><input id="m" type="number" value="0" /></td></tr><tr><td>n=</td><td><input id="n" type="number" value="0" /></td></tr><tr><td colspan="2"><input type="button" value="Calculate!" onclick="document.getElementById('out').value=a(document.getElementById('m').value, document.getElementById('n').value)" /></td></tr><tr><td colspan="2"><input id="out" disabled="disabled" type="text" /></td></tr></tbody></table>


4

JavaScript (ES6) - 34

A=(m,n)=>m?A(m-1,!n||A(m,n-1)):n+1

Ve bir test:

> A=(m,n)=>m?A(m-1,!n||A(m,n-1)):n+1;s=new Date().getTime();console.log(A(3,10),(new Date().getTime() - s)/1000)
8189 16.441

3

Coq, 40

nat_rec _ S(fun _ b n=>nat_iter(S n)b 1)

Bu tür bir işlevdir nat -> nat -> nat . Coq sadece toplam fonksiyonların oluşturulmasına izin verdiğinden, Ackermann'ın tekrarlanmasının sağlam olduğunu resmi bir kanıtı olarak görür.

Demo:

Welcome to Coq 8.4pl6 (November 2015)

Coq < Compute nat_rec _ S(fun _ b n=>nat_iter(S n)b 1) 3 10.
     = 8189
     : nat

Not: adını bu meydan, sonra serbest Coq 8.5, nat_iteriçin Nat.iter.



2

Mathematica, 46 bayt

0~a~n_:=n+1
m_~a~n_:=a[m-1,If[n<1,1,a[m,n-1]]]

Tam olarak bir dakika sürüyor a[3,10]. Mathematica'nın varsayılan özyineleme sınırının a[3,8](en azından makinemde) ve ötesinde çok küçük olduğunu, ancak bu yapılandırma yapılandırarak düzeltilebileceğini unutmayın.

$RecursionLimit = Infinity

1
Vay, yani JS'nin Mathematica'dan 25 kat daha hızlı olduğunu mu söylüyorsun?
Doktor,

@Optimizer En azından özyinelemeye gelince ... Sanırım, hangi tanımı kullanacağını ve Ifbir fonksiyon olmanın daha yavaş olduğunu anlamak zorunda olsa bile, sanırım bir kısmı .
Martin Ender

1
Doldurma işleminde 0,07 saniye sürer. Yani m_~a~n_:=m~a~n=...
Mark Adler

@MarkAdler Bu, Mathematica'daki hatıraları yapmanın gerçekten güzel bir yolu!
Martin Ender

2

Lambdas ile javascript, 34

A=(m,n)=>m?A(m-1,n?A(m,n-1):1):n+1

Tipik bir cevap, daha kısa bir şey yapamaz.


2

Haskell, 48 44 karakter (liste için 36)

Diğer Haskell çözümü kadar kısa olmasa da, bu bir kayda değer çünkü Ackermann işlevini sonsuz bir liste olarak ifade ediyor, sanırım çok temiz. Sonuç, [m, n] pozisyonunda A (m, n) değerini tutacak şekilde sonsuz bir listedir (sonsuz listelerden ) .

Sonsuz listenin kendisi:

iterate(tail.(`iterate`1).(!!))[1..]

Bir fonksiyon olarak (şartnameye uymak için):

i=iterate;m%n=i(tail.(`i`1).(!!))[1..]!!m!!n

Formülasyon, Ackermann fonksiyonu için genel / ortak durumun soldaki değeri yukarıdaki satırda bir indeks olarak kullanmak olduğunu gözlemleyerek elde edildi. Bu özyinelemenin temel durumu (yani bir satırın en soldaki sütunu, yani A (m, 0) ) yukarıdaki satırdaki en soldaki ikinci değeri kullanmaktır. İçin temel durum bu yineleme olduğu = n + 1 bir (0, N) durumda, başka bir deyişle birinci satırdır [1..].

Böylece alırız

let a0 = [1..]
let a1 = tail $ iterate (a0 !!) 1  -- 'tail' because iterate starts by applying
let a2 = tail $ iterate (a1 !!) 1  -- the function 0 times
-- etc

Sonra sadece bu desene dayanarak başka bir yineleme düzeyi ekleriz ve bazı anlamsız hokkabazlık yaparız .


Yani, iteratetek bir harf adına takma ad atabilirsiniz yanii=iterate;ack=i ...
proud haskeller 23:14

@ proudhaskeller oh evet, bunu düşünmedim. Teşekkürler! Operatör adınızı ödünç almak da.
FireFly

2

Küçük Lisp , 70 (yarışma dışı)

Bu dil sorudan daha yeni olduğu için rekabetin dışında kalıyor (A 3 10)ve bir yığın taşması nedeniyle soruda gerektiği şekilde çalıştırmayı başaramıyor.

(d A(q((m n)(i m(i n(A(s m 1)(A m(s n 1)))(A(s m 1)1))(s n(s 0 1))))))

Bu AAckermann fonksiyonunu hesaplayan bir fonksiyon tanımlar . biçimlendirilmiş:

(d A
   (q( (m n)
       (i m
          (i n
             (A (s m 1)
                (A m
                   (s n 1)
                 )
              ) 
             (A (s m 1)
                1
              )
           )
          (s n
             (s 0 1)
           )
        )
    ) )
 )

Tüm yerleşik makroları ( d(tanımla) ve q(alıntı) ve i(eğer)) ve bir yerleşik işlevi (s - çıkarmak) kullanıyoruz.

i Koşul, bir sayı> 0 olduğunda (ve aksi takdirde yanlış olan kısım olduğunda) gerçek kısmını uygular, bu yüzden burada açık bir karşılaştırma yapmak zorunda değiliz.

sKullanılabilir tek aritmetik işlem ise, n-1/ için m-1olduğu gibi / (s n (s 0 1))için de kullanırız n+1.

Küçük lisp kuyruk özyineleme optimizasyonu kullanıyor, ancak bu sadece parametreler için kullanılan arama Aiçin değil , sonuçtaki dış arama için yardımcı olur A(m, n-1).

İle benim küçük lisp uygulaması JVM üzerinde Seylan, bu kadar çalışır (A 3 5) = 253, ancak hesaplamak çalışırken yıkmak gibi görünüyor (A 2 125)(aynı sonucu vermesi gereken) doğrudan. Bunu sonradan hesaplarsa (A 3 4) = 125, JVM tercümanımdaki bazı orta işlev çağrıları satır içi için daha fazla özyineleme derinliği sağlayacak kadar işlevleri optimize etmek zorunda görünüyor. Garip.

Referans uygulama için ayağa kalkar (A 3 5) = 253ve ayrıca (A 2 163) = 329, ancak başarılı olamaz (A 2 164)da az dolayısıyla ve (A 3 6) = (A 2 253).


bu, boşluk ve parantez için rekabetçi bir tasarruf olabilir;)
cat

2

Go, 260 243 240 122 bayt

Sorunun hiç kimseye izin vermediğini görmedim.

rekabetten uzak ama ben bu dili öğreniyorum ve test etmek istedim.

func (m,n int)int{r:=0
switch{case m==0&&n!=0:r=n+1
case m!=0&&n==0:r=a(m-1,1)
case m!=0&&n!=0:r=a(m-1,a(m,n-1))}
return r}

gibi kullanın go run ack.gove sonra iki sayı girin mve n. m> 4 veya n> 30 ise, uygulama süresi yarım dakikadan fazla olabilir.

için m=3 n=11:

$ time go run ack
16381
real    0m1.434s
user    0m1.432s
sys     0m0.004s

düzenleme : switchüzerinde if/elseve nokta ithalatı geçiş yaparak toplam 17 bayt kaydedildi


1
Daha da iyisini yapabilirsin! switch 0 {case m:r=n+1 case n:r=a(m-1,1) default:r=a(m-1,a(m,n-1))}Go'nun switchifadesi çok güzel esnek!
EMBLEM

@EMBLEM Teşekkürler, çok uzun zamandır bir satır Go yazmıştım, fakat başka Go-golfçuların olduğunu görmekten çok memnun oldum: D
cat

1

Haskell: 81 69 bayt

a::Int->Int->Int
a 0 n=n+1
a m 0=a (m-1) 1
a m n=a (m-1) a m (n-1)

a 3 10 yaklaşık 45 saniye sürer.


1
Bu kod golf, bu yüzden mümkün olan en kısa kodu almaya çalışmalısınız. örneğin, gereksiz alanları ve açık türü kaldırın
proud haskeller

ayrıca dördüncü sıradaki
parenleri




1

R - 54 52

Bunu kafamı R'nin etrafına sokmak için bir bahane olarak kullandım, bu yüzden bu gerçekten çok kötü bitti :)

a=function(m,n)"if"(m,a(m-1,"if"(n,a(m,n-1),1)),n+1)

Örnek çalışma

> a(3,8)
[1] 2045

Bunun ötesinde bir şey için yığın taşması alıyorum

T-SQL-222

Ben de T-SQL'i yapmaya çalışacağımı düşündüm. SQL'de özyineleme o kadar iyi olmadığından farklı bir yöntem kullandım. 4,2'nin üzerindeki her şey bombalar.

DECLARE @m INT=4,@n INT=1;WITH R AS(SELECT 2 C, 1 X UNION ALL   SELECT POWER(2,C),X+1FROM R)SELECT IIF(@m=0,@n+1,IIF(@m=1,@n+2,IIF(@m=2,2*@n+3,IIF(@m=3,POWER(2,@n+3)-3,IIF(@m=4,(SELECT TOP(1)C FROM R WHERE x= @n+3)-3,-1)))))

R submisson için, {}Yığın taşması sınırına yardımcı olmamasına rağmen , R 'nin TCO'su olmadığı için ihtiyacınız yok gibi görünüyor ...
Giuseppe

@Giuseppe teşekkürler ... savunmamda, o zamanlar
yeniydim

1

brainfuck , 90 bayt

>>>>+>,>,<<[>[>[-[->>>+<<<]<[->+>>+<<<]>-[-<+>]>+>>>>>]<[->+>>]]<[>>+[-<<<+>>>]<<-]<<<]>>.

Çevrimiçi deneyin!

Sayı olarak IO ile isteğe bağlı boyutta hücre boyutunda bir uygulama üstlenir. -6 byte negatif hücre kullanmak sakıncası yoksa.

Doğru ayarları işaretlemeniz şartıyla, bağlantılı tercümanda yaklaşık 30 saniye içinde 3,8 bitir. Mevcutsa önüne Girilen sayıları yazın \örneğin s, 3,9olan \3\9.


1

Tcl , 67 bayt

proc tcl::mathfunc::A m\ n {expr {$m?A($m-1,$n?A($m,$n-1):1):$n+1}}

Çevrimiçi deneyin!


Tcl , 77 bayt

proc A m\ n {expr {$m?[A [expr $m-1] [expr {$n?[A $m [expr $n-1]]:1}]]:$n+1}}

Çevrimiçi deneyin!

Çevrimiçi derleyicide zaman aşımı nedeniyle çalışmaz, ancak yerel bir Tcl yorumlayıcısında iyi çalışır. AHesaplanacak her bir çift için hesaplamanın ne kadar sürdüğünü görmek için her kök çağrısının işlevini profillendirdim {m,n}:

m=0, n=0, A=1, time=3.5e-5 seconds
m=0, n=1, A=2, time=2e-6 seconds
m=0, n=2, A=3, time=8e-6 seconds
m=0, n=3, A=4, time=1e-6 seconds
m=0, n=4, A=5, time=2e-6 seconds
m=0, n=5, A=6, time=1e-6 seconds
m=0, n=6, A=7, time=1e-6 seconds
m=0, n=7, A=8, time=1e-6 seconds
m=0, n=8, A=9, time=1e-6 seconds
m=0, n=9, A=10, time=0.0 seconds
m=0, n=10, A=11, time=1e-6 seconds
m=1, n=0, A=2, time=4e-6 seconds
m=1, n=1, A=3, time=6e-6 seconds
m=1, n=2, A=4, time=1e-5 seconds
m=1, n=3, A=5, time=1.2e-5 seconds
m=1, n=4, A=6, time=1.5e-5 seconds
m=1, n=5, A=7, time=2e-5 seconds
m=1, n=6, A=8, time=2e-5 seconds
m=1, n=7, A=9, time=2.6e-5 seconds
m=1, n=8, A=10, time=3e-5 seconds
m=1, n=9, A=11, time=3e-5 seconds
m=1, n=10, A=12, time=3.3e-5 seconds
m=2, n=0, A=3, time=8e-6 seconds
m=2, n=1, A=5, time=2.2e-5 seconds
m=2, n=2, A=7, time=3.9e-5 seconds
m=2, n=3, A=9, time=6.3e-5 seconds
m=2, n=4, A=11, time=9.1e-5 seconds
m=2, n=5, A=13, time=0.000124 seconds
m=2, n=6, A=15, time=0.000163 seconds
m=2, n=7, A=17, time=0.000213 seconds
m=2, n=8, A=19, time=0.000262 seconds
m=2, n=9, A=21, time=0.000316 seconds
m=2, n=10, A=23, time=0.000377 seconds
m=3, n=0, A=5, time=2.2e-5 seconds
m=3, n=1, A=13, time=0.000145 seconds
m=3, n=2, A=29, time=0.000745 seconds
m=3, n=3, A=61, time=0.003345 seconds
m=3, n=4, A=125, time=0.015048 seconds
m=3, n=5, A=253, time=0.059836 seconds
m=3, n=6, A=509, time=0.241431 seconds
m=3, n=7, A=1021, time=0.971836 seconds
m=3, n=8, A=2045, time=3.908884 seconds
m=3, n=9, A=4093, time=15.926341 seconds
m=3, n=10, A=8189, time=63.734713 seconds

{m,n}={3,10}Bir dakikadan biraz daha uzun sürdüğü için son çift için başarısız olur .

Daha yüksek değerler için m, recursionlimitdeğeri arttırmak gerekecektir .


65 bayta kısaltmak istemem ama sorusun gerekliliğini karşılamayacak "İşiniz bir dakikadan az bir sürede m ≤ 3 ve n ≤ 10 değerlerinde A (m, n) değerini bulmalı." Bu olmadan {}TIO'da zaman aşımına uğrar ve son iki girişin demosunu yapmaz.

Tcl , 65 bayt

proc tcl::mathfunc::A m\ n {expr $m?A($m-1,$n?A($m,$n-1):1):$n+1}

Çevrimiçi deneyin!


0

J: 50

>:@]`(1$:~<:@[)`(<:@[$:[$:_1+])@.(0>.[:<:@#.,&*)M.

0 ... 3 - 0 ... 10 için bir saniyenin kesirinde döner:

   A=:>:@]`(1$:~<:@[)`(<:@[$:[$:_1+])@.(0>.[:<:@#.,&*)M.
   timespacex 'res=:(i.4) A"0 table (i.11)'
0.0336829 3.54035e6
   res
┌───┬──────────────────────────────────────────┐
│A"0│0  1  2  3   4   5   6    7    8    9   10│
├───┼──────────────────────────────────────────┤
│0  │1  2  3  4   5   6   7    8    9   10   11│
│1  │2  3  4  5   6   7   8    9   10   11   12│
│2  │3  5  7  9  11  13  15   17   19   21   23│
│3  │5 13 29 61 125 253 509 1021 2045 4093 8189│
└───┴──────────────────────────────────────────┘

Not: "0, sol ve sağ diziyi kaldırmak ve uzunluk hataları oluşturmak yerine, her bir eleman üzerinde bir A yapmaya yardımcı olur. Fakat 9 = 2 A3 için gerekli değildir.



0

APL, 31

{⍺=0:⍵+1⋄⍵=0:1∇⍨⍺-1⋄(⍺-1)∇⍺∇⍵-1}

Oldukça basit. Argümanları ters çevirerek bir bayttan tasarruf etmek için ⍨ karakterini bir kez kullanır. M'yi sol argüman, n'yi sağ argüman olarak alır.

TryAPL.org


0

Ruby, 65

h,a={},->m,n{h[[m,n]]||=m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]])}

açıklama

Bu, problem tanımında verilen algoritmanın oldukça basit bir çevirisidir.

  • Giriş bir lambda argümanı olarak alınır. İkiInteger s bekleniyor.
  • Hız ve yığın taşması hatalarından kaçınmak için cevaplar içinde not edilir Hash h. ||=Operatör daha önce hesaplanmamıştır bir değerin hesaplanması için kullanılmaktadır.

a[3,10] makinemde ~ 0.1 saniye olarak hesaplanır.

İşte bir ungolfed versiyonu

h = {}
a = lambda do |m,n|
  h[[m,n]] ||= if m < 1 
    n + 1
  elsif n < 1
    a[m-1,1]
  else
    a[m-1,a[m,n-1]]
  end
end

a[3,10]
makineme

Golf nitpicks: Sen değişebilir m<1?(n+1):(n<1?a[m-1,1]:a[m-1,a[m,n-1]])içinm<1?n+1:a[m-1,n<1?1:a[m,n-1]]
Sadece güzel Sanatı

0

Fare-2002 , 99 83 bayt

$Y1%j:j.0=m:2%k:k.0=n:m.n.>[k.1+!|m.n.<[#Y,j.1-,1;|m.n.*0=[#Y,j.1-,#Y,j.,k.1+;;]]]@

0

Java, 274 bayt

import java.math.*;class a{BigInteger A(BigInteger b,BigInteger B){if(b.equals(BigInteger.ZERO))return B.add(BigInteger.ONE);if(B.equals(BigInteger.ZERO))return A(b.subtract(BigInteger.ONE),BigInteger.ONE);return A(b.subtract(BigInteger.ONE),A(b,B.subtract(BigInteger.ONE)));}}

Bu hesaplar A(3,10)birkaç saniye içinde ve sonsuz bellek ve yığın alanı göz önüne alındığında, herhangi bir kombinasyonu hesaplayabilir bve Bsürece sonuç 2 altında olduğu gibi 2147483647 -1.


Bir süre geçtiğini biliyorum ama bunu 185 byte'a kadar golf edebilirsiniz :import java.math.*;BigInteger A(BigInteger b,BigInteger B){return b.equals(B.ZERO)?B.add(B.ONE):B.equals(B.ZERO)?A(b.subtract(B.ONE),B.ONE):A(b.subtract(B.ONE),A(b,B.subtract(B.ONE)));}
Kevin Cruijssen

0

Seylan, 88 87 85

alias I=>Integer;I a(I m,I n)=>m<1then n+1else(n<1then a(m-1,1)else a(m-1,a(m,n-1)));

Bu basit bir uygulamadır. biçimlendirilmiş:

alias I => Integer;
I a(I m, I n) =>
        m < 1
        then n + 1
        else (n < 1
            then a(m - 1, 1)
            else a(m - 1, a(m, n - 1)));

Takma ad yalnızca bir bayt kurtarır, onsuz ( Integerbunun yerine yazı ile I) 86 bayta ulaşırdık. Başka iki bayt değiştirerek kaydedilebilir == 0tarafından< 1 iki kez.

Varsayılan ayarları ile ceylon run, A(3,12) = 32765(ve A(4,0) = 13) 'ye kadar çalışır , ancak A(3,13)(ve bu nedenle de A(4,1)) yığın taşması hatası verir. ( bilgisayarımda A(3,12)yaklaşık 5 saniye, A(3,11)yaklaşık 3 saniye sürer .)

Kullanımı ceylon run-js(yani, node.js'de JavaScript'i derlemenin sonucunu çalıştırmak) çok daha yavaştır (1 dakika 19 sn için gerekir A(3,10)) ve A(3, 11)1 için çalıştırıldıktan sonra bir "Maksimum çağrı yığını boyutu aşıldı« (varsayılan ayarları kullanarak) için zaten en az 30 s.


Özyineleme olmadan Seylan, 228

Bonus olarak, özyinelemeli olmayan bir sürüm (elbette daha uzun, ancak yığın taşmalarına karşı bağışıklık - bir noktada yetersiz bellek hatası alabilirsiniz).

import ceylon.collection{A=ArrayList}Integer a(Integer[2]r){value s=A{*r};value p=s.addAll;while(true){if(exists m=s.pop()){if(exists n=s.pop()){if(n<1){p([m+1]);}else if(m<1){p([n-1,1]);}else{p([n-1,n,m-1]);}}else{return m;}}}}

biçimlendirilmiş:

import ceylon.collection {
    A=ArrayList
}

Integer a(Integer[2] r) {
    value s = A { *r };
    value p = s.addAll;
    while (true) {
        if (exists m = s.pop()) {
            if (exists n = s.pop()) {
                if (n < 1) {
                    p([m + 1]);
                } else if (m < 1) {
                    p([n - 1, 1]);
                } else {
                    p([n - 1, n, m - 1]);
                }
            } else {
                // stack is empty
                return m;
            }
        }
    }
}

Bilgisayarımda özyinelemeli sürümden çok daha yavaş: A(3,11)9.5 saniye, A(3,12)34 saniye, A(3,13)2:08 dakika, A(3,14)8:25 dakika sürüyor. (Başlangıçta, şu anda sahip olduğum, aynı boyutta çok daha yavaş olan tote'ler yerine tembel yinelemeleri kullanan bir sürümüm vardı).

Biraz daha hızlı (21 saniye için A(3,12)) (aynı zamanda bir bayt daha uzun) s.pushbunun yerine kullanılan bir sürümdür s.addAll, ancak her birinin yalnızca bir tamsayı kullanması için birden çok numara eklemek için birkaç kez çağrılması gerekir. ArrayList yerine LinkedList kullanmak çok daha yavaştır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.