Hipermetropiyi değerlendirin


12

Bunun biraz math-y olduğunu anlıyorum, ama - işte gidiyor.

Matematikte, hipermetropi dizisi, halefin tekli işlemiyle başlayan, daha sonra ikili toplama, çarpma ve üs alma işlemleriyle devam eden sonsuz bir aritmetik işlem dizisidir (hipermetroperasyonlar olarak adlandırılır), ardından dizi, ötesine uzanan diğer ikili işlemlerle devam eder. doğru çağrışım kullanarak üs alma.

Amacınız giriş olarak üç x, y ve n tamsayısını alan ve x ve y üzerinde n'inci hipermetropinin sonucunu çıkaran bir program yazmaktır.

Örneğin

1 1 1 çıkışlar 2

2 4 4 çıkışlar 65536

3 3 4 çıkışlar 7625597484987

  • Program en kısa kod bitiyle yazılmalıdır.
  • STDINBir dosyadan ya da dosyadan girdi alabilirsiniz .
  • Kütüphane işlevlerine izin verilmiyor.
  • Giriş kısıtlamaları: n ≥ 1 olacaktır.

Başınızı buralara saramamanız durumunda http://en.wikipedia.org/wiki/Tetration'ın iyi bir açıklaması vardır.


Nedir n=1? E? Er x+yya x+1, 1 1 1dönmelidir2
John Dvorak

Bir yerde bir hata yaptığımı biliyordum :) sabit, thx.
Soham Chowdhury

1
Bana sahte bir kod yazdım, sonra bunun aslında geçerli bir Ruby kodu olduğunu fark ettim (neredeyse :-()
John Dvorak

1
Hayır, sadece n> = 1.
Soham Chowdhury

Yanıtlar:


4

Ruby, yavaş, 86 84 83 karakter

def f x,y,n
n>1?(c=x;2.upto(y){c=f(x,c,n-1)};c):x+y
end
p f *gets.split.map(&:to_i)

Ruby, hızlı, 96 94 93 karakter

def f x,y,n
n>1?(n>2?(c=x;2.upto(y){c=f(x,c,n-1)};c):x*y):x+y
end
p f *gets.split.map(&:to_i)

İlk sürümü yolu bir versiyonunu ekledi böylece, son test durumu ile çok yavaş yerine ek taban vaka olarak kullandığı çarpma. İlk sürümün hesaplanması yıllar alır 3 3 4; ikincisi anlıktır (yerel IRB konsolunda; web sürümü biraz daha yavaştır).

Ruby'nin birkaç güzelliği burada ortaya çıkıyor:

Hemen hemen her ifade yakutta bir ifadedir. Böylece, etrafta yeterli parantez olması koşuluyla üçlü operatör içinde noktalı virgül doldurabilirsiniz. Coffeescript bunu ödünç aldı. Aynı zamanda Ruby'nin “parens gerekli değil” çağrı sözdizimini ödünç aldı.

Örtük dönüşler: bu harika bir özelliktir ve öncekinden sonra gelir. Gerçekten de, bir fonksiyonun son satırına başlamak, returngolf olmasa bile topal olarak kabul edilir.

Sayılar yakuttaki nesnelerdir (hatta nullbir nesnedir). Ruby'de, tamsayılar timesbirkaç kez geçirilen bloğu yürüten yönteme sahiptir. Bu Ruby'nin birçok yineleyici yönteminden sadece biri. Burada uptoyöntem , iki karakter daha bize kaydetmemize timesizin verir.

tekli *burada uyarısı operatörüdür. Bir diziyi bağımsız değişken listesine dönüştürür. Tıpkı Javascript gibi Function#apply, ama daha kısa ve daha iyi.

unary &bir prosedürü bloğa dönüştürür. :to_iBir sembol olsa da, oldukça iyi bir prosedüre dönüşür. Yani, to_iargümanını çağıran ve sonucu döndüren bir prosedüre dönüşür . Yığın Taşması hakkında daha fazla bilgi.

n=3Temel durum olarak kullanarak daha da hızlı almak mümkün olabilir , ancak korkarım buna gerek yok. Yine de, yakutun başka bir güzelliği olan üssü operatörü sayesinde sadece 11 karaktere mal olur **. Python bu operatöre sahip, ancak ilk değil (@ aka.nice belirtildiği gibi - teşekkürler -, Fortran zaten bu operatöre sahipti).

çevrimiçi yakut tercüman: http://repl.it/Ikj/1


Güzel, ama hala bir çıktı bekliyorum 3 3 4:) çok yavaş.
Soham Chowdhury

@SohamChowdhury temel durum ekidir. Temel bir çarpma durumunda, çok yavaş (ve daha uzun) olacaktır. Bunun yerine üs ile test etmenizi öneririm ;-)
John Dvorak

Bu belki kullanım memoization için zaman kazanmak, ama bu bazı bayt (epeyce) mal olacak
John Dvorak

Sonra başka bir sürüm ekle :)
Soham Chowdhury

1
operatör ** 50'li yıllarda FORTRAN'da zaten mevcuttu ve ALGOL yukarı ok ile 1 karakter daha az olurdu
aka.nice

6

APL, 62

{1=3⌷⍵:2⌷+\⍵⋄0=2⌷⍵:(⍵[3]⌊3)⌷⍵[1],0,1⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1}⎕

{...}⎕: Değerlendirilmiş girdiyi alır (boşlukla ayrılmış sayılar sayısal bir diziye göre değerlendirilir) ve bu işleve işlevi uygular.

1=3⌷⍵:: N eşittir 1 ...
2⌷+\⍵: İlk 2 öğenin (x + y) toplamı ...
⋄0=2⌷⍵:: y eşittir 0 ...
(⍵[3]⌊3)⌷⍵[1],0,1: Sayısal dizi [x, 0,1] ve dönüş dizini oluşturun min(n,3)...
⋄∇⍵[1],(∇⍵-0 1 0),3⌷⍵-1: Başka dönüş ∇ (x, ∇ (x, y-1, n), n-1). (Self öz referanstır)


Bir işlevi alan ve sonraki hipermetropi döndüren bir "hiper-raiser" operatörü var

{⍺⍺/⊃⍴/⌽⍵}

Örneğin +{⍺⍺/⊃⍴/⌽⍵}, çarpma fonksiyonu ve +{⍺⍺/⊃⍴/⌽⍵}5 3çıktıları 15 olurdu .

Ama bunu tekrarlayamazsın. Belki başka biri yapabilir.


Ah, APL. Her gün basitlik için Python'u yener. </sarcasm> Bunu nasıl çalıştırırım?
Soham Chowdhury

2

Python, 83

( Flornquake'in cevabına göre )

def h(x,y,n):r=n>2;exec"r=h(x,r,n-1);"*y*(n>1);return(x+y,r)[n>1]
print h(*input())

Büyük sonuçlar için çok yavaş.

İçin 2, 4, 4çıkış olduğunu 65536.


"Çok yavaş" 86 karakterli çözümümün kötü olarak değerlendirilmesinin nedenidir.
John Dvorak

1
@ JanDvorak: Sizce neden kötü kabul edildi? Soham Chowdhury yavaş olduğunu ve çözümün yerine başka bir versiyon eklemeniz gerektiğini söyledi. (Ama belki de yanlış anladım.)
Monica'yı

Haklısın; kısa versiyonu geri yükledi. Şimdi senden daha uzun bir karakterim.
John Dvorak

@WolframH kesinlikle. Sürümleri her zaman güzel.
Soham Chowdhury

2

Python, 96 92

def h(x,y,n):r=1;exec(n>2)*y*"r=h(x,r,n-1);";return(r,(x+y,x*y)[n>1])[n<3]
print h(*input())

Giriş: 3, 3, 4
Çıkış:7625597484987

Birkaç @ WolframH'ın fikirleri kullanılarak kısaltıldı .


2

Golfscript, yavaş, 39 karakter

 ~{\(.{3${[4$\2$4$.~}4$(*}{;;+}if])\;}.~

(canlı bağlantı)

Bu, n = 1 (ekleme) (yani yavaş) temel durumuna sahip standart özyinelemeli algoritmadır. Ruby çözümümde kullandığımla aynı

İşte ek açıklamalarım içeren bir sürüm (çoğunlukla yığın tutma). Daha sonra eklediğim bir optimizasyon içermiyor:

~{            #read the input and do (x y n f)
 \(.{         #(x y f n-1); if(n-1)
  3${         #(x y f n-1 c)
   4$\2$4$.~  #(x y f n-1 x c n-1 f); call
  }3$(*       #y-1 times
  {\;}4*
 }{           #else
  ;;+         #return (x+y)
 }if
}.~           #once

~eval operatörüdür. Dizeler olması durumunda, dizeye GolfScript programı olarak davranır. Neyse ki, boşlukla ayrılmış bir tam sayı listesi, bu tam sayıları yığına iten geçerli bir GolfScript programıdır. Bununla karşılaştırıldığında, giriş rutininin önceki sürümü ( " "/{~}/, boşluğa bölünmüş ve her biri eval) oldukça topal. İşlev durumunda, işlevi çağırır. Öncesinde .(klon) olduğunda, işlevi ilk argüman olarak kendisi ile çağırır.

Golfscript özyinelemeli algoritmalar yapmak için tam olarak uygun görünmüyor. Kuyruk çağrısı optimize edilemeyen özyinelemeli bir algoritma istiyorsanız, değişkenlerinizi korumak için yığın kareleri oluşturmanız ve yok etmeniz gerekir. Çoğu dilde bu otomatik olarak yapılır. Golfscript'te, değişkenleri gerçekten kopyalamanız (aslında yığın girişleri) ve artık ihtiyacınız olmayan yığın girişlerini imha etmeniz gerekir. Golfscript'te yığın çerçeve kavramı yoktur. GolfScript'in yığın tabanlı bir dil olduğunu mu söyledim?

İlk gereklilik anlaşılabilir. Argümanları bir şekilde belirtmelisiniz. Sadece orijinal konumlarını koruyorlarsa hoş olur. İkinci gereksinim, özellikle dönüş değeri yığının üstünde olduğu için ve golfscript'in herhangi bir yığın öğesini silme yeteneğinden yoksun olduğu için talihsizdir. Yığını döndürebilir ve yeni üst öğeyi atabilirsiniz, ancak bu hızlı bir şekilde birikir. \;iyi. \;\;\;\;\;değil. Sen yapabilir \;bir döngüde ( {\;}9*; maliyeti: 6 karakter 99 elemente kadar atmak 9 elemanları, veya 7 karakter kadar atmak), ancak daha iyisini yapabiliriz:

Golfscript birinci sınıf dizilere sahiptir. Ayrıca dizi değişmez dizimine sahiptir [1 2 3 4]. Ne beklenmedik olmasıdır [ve ]aslında sözdizimi parçası değildir. Bunlar yalnızca iki işleçtir: [yığındaki geçerli konumu işaretler ve ]dizi başlangıcını bulana veya yığının bitip bitene kadar her öğeyi toplar ve işareti atar. Hatta bu ikisini parçalayabilir ve ne olduğunu görebilirsiniz. Oldukça ilginç bir şey:

Golfscript'te yığın çerçeve kavramı yok mu dedim? Yalan söyledim. Bu yığın çerçevesi: [. Bir kerede tüm bunu atabiliriz: ];. Peki ya iade değerini korumak istiyorsak? İşlev girişindeki yığın çerçevesini kapatabilirsiniz (daha sonra ilginç bir kavram değil, diziye göre hafifçe karıştırılmış bir sürümümüz vardır) veya yığın çerçevesini kapatabilir ve tamamen kaldırmak yerine son öğesini alabiliriz: ]-1=ya da uncons son öğe yerine, ve olabilir ardından çerçeveyi atmak: ])\;. Aynı uzunluktadırlar, ancak ikincisi biraz daha serindir, bu yüzden kullanıyorum.

Yani, temizlik yapmak için 6 veya 7 karakter yerine, 5 ile yapabiliriz. Yine de bunun daha fazla golf oynayabileceğini hissediyorum, ama hey, bir karakter kaydettik.


"işlevi kendisiyle ilk argüman olarak çağırıyor" - özyineleme için ilginç bir fikir
aditsu, SE'nin EVIL

1

Smalltalk Squeak 4.x lezzet birçok bayt!

71 karakterde Tamsayı'da özyinelemeli formlardan birini uygulayabilirim

f:y n:n n=1or:[^(2to:y)inject:self into:[:x :i|self f:x n:n-1]].^self+y

Sonra bir dosya veya FileStream stdin okumak bana bir kol mal olacak ... Gıcırtı bir komut dosyası dili olarak tasarlanmamıştı. Bu nedenle, sorunla ilgisi olmayan kendi genel amaçlı yardımcı programları oluşturmak için birçok bayt harcayacağım:

Bu 21 karakter yöntemini Akışta uygulayın (depolayıcıları atlamak için)

s self skipSeparators

Bu 20 karakterlik yöntemi Davranışta uygulayın (Akıştan bir örnek okumak için)

<s^self readFrom:s s

Sonra String'de 28 karakter (bir dosya tanıtıcısı oluşturmak için)

f^FileDirectory default/self

Sonra FileDirectory içinde 59 karakter (bir readStream oluşturmak için)

r^FileStream concreteStream readOnlyFileNamed:self fullName

Sonra BlockClosure'da 33 karakter (n kez değerlendirmek için)

*n^(1to:n)collect:[:i|self value]

Sonra Array'da 63 karakter (alıcı ile argümanı ve Array'dan alınan argümanları değerlendirin)

`s^self first perform:s asSymbol withArguments:self allButFirst

daha sonra bu 31 karakter snippet'ini x adlı dosyadan okunacak herhangi bir yerde değerlendirerek sorunu çözün

|s|s:='x'f r.[0class<s]*3`#f:n:

Yardımcı programları saymadan bile, 71 + 31 = 102 karakter zaten ...

Şimdi, codeGolf kaybetmek emin eminim, ben Integer bir daha komik bir uygulama var:

doesNotUnderstand:m
    (m selector allSatisfy:[:c|c=$+])or:[^super doesNotUnderstand:m].
    self class compile:
        m selector,'y y=0or:[^(2to:y)inject:self into:[:x :i|self'
        ,m selector allButLast,'x]].^'
        ,(Character digitValue:()asBit)
        ,(m selector size-2min:1)hex last.
    thisContext sender restart

Bu yöntem yoksa (n iletisinin alıcısı tarafından anlaşılamazsa) n + 'dan yapılan ikili iletileri tanımlar (derler) ve gönderen bağlamının başlangıcında yürütmeyi yeniden başlatır. Ek satır başı ve okunabilirlik için boşluklar ekledim.

Bunun (m selector size-2min:1)hex lastkısa bir biçimi olduğunu unutmayın (m selector size>2)asBit printString.

Smalltalk kötü süper güçlerini göstermek olmasaydı, son ifade daha kısa ve daha basit ile değiştirilebilir

^m sendTo:self

Şimdi Karakter'e 28 karakter yardımcı programı uygulayın (bir String'de n kez tekrarlamak için)

*n^String new:n withAll:self

Sonra bu 43 karakter ifadesini değerlendirin:

|i s|i:=0class.s:='x'f r.[i<s]*2`($+*(i<s))

Tamsayı'da uygulayarak 10 karakter daha hızlandırabiliriz:

++y^self*y

Biz yerini alabilir çünkü ve bu durumda biz de daha kısa koduna sahip ^',(m selector size-2min:1)hex lastolan^1'

Böyle yüksek bir fiyat için, kod ikinci tamsayı = 0 ile çalışır :)



0

AXIOM Bilgisayar Cebir Sistemi, bayt 69

p(x,y,n)==(n<=1=>y+x^n;n=2=>y*x;n=3=>x^y;y<=0=>1;p(x,p(x,y-1,n),n-1))

Ölçek:

(2) -> p(1,1,1)
   (2)  2
                                                 Type: Expression Integer
                                   Time: 0.05 (IN) + 0.03 (OT) = 0.08 sec
(3) -> p(2,4,4)
   (3)  65536
                                                 Type: Expression Integer
                                                              Time: 0 sec
(4) -> p(3,3,4)
   (4)  7625597484987
                                                 Type: Expression Integer
                                                              Time: 0 sec

Bu, bazı özyinelemeyi ortadan kaldırır ... Bazı x ve y dönüşlerinde takas edebilirim ... başka test değerleri var mı?


0

APL (NARS), karakter 61, bayt 122

{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}

Ölçek:

  h←{(x y n)←⍵⋄n≤1:y+x*n⋄n=2:x×y⋄n=3:x*y⋄y≤0:1⋄∇x,(∇x(y-1)n),n-1}
  h 1 1 1
2
  h 2 4 4
65536
  h 3 4 4
∞
  h 3 3 4
7625597484987
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.