Hofstadter H-dizisi


15

Tanım

  • a(0) = 0
  • a(n) = n-a(a(a(n-1))) tamsayı için n > 0

Görev

Negatif olmayan tamsayı verildiğinde nçıktı a(n).

testcases

n     a(n)
0     0
1     1
2     1
3     2
4     3
5     4
6     4
7     5
8     5
9     6
10    7
11    7
12    8
13    9
14    10
15    10
16    11
17    12
18    13
19    13
20    14
10000 6823

Referanslar


Hofstadter dizileri ile ilgili zorluklar: 1 , 2 , 3
Martin Ender

4
Ve hala GEB'ye başvurmanız gerektiğini düşünüyorum ...
Martin Ender

1
Sayı-teori burada nasıl önemlidir?
flawr

1
@flawr facepalm Tekrar deneyeyim: Gödel, Escher, Bach: Sonsuz Altın Örgü
Stig Hemmer

1
@StigHemmer Aslında facepalm artık kendi Emoji'sine sahip: 🤦
Tobias Kienzler

Yanıtlar:


20

Haskell, 23 22 bayt

f 0=0
f n=n-f(f$f$n-1)

Sadece dizinin tanımını kullanır. f(f$f$n-1)eşittir f (f (f (n-1))).

Ölçek:

main = putStrLn . show $ map f [0..20]
-- => [0,1,1,2,3,4,4,5,5,6,7,7,8,9,10,10,11,12,13,13,14]

Bayt için Anders Kaseorg'a teşekkürler !


(f$f$f$n-1)= f(f$f$n-1)bayt kaydeder.
Anders Kaseorg


9

Mathematica, 20 bayt

Bayt sayısı ISO 8859-1 (veya uyumlu) kodlamayı varsayar $CharacterEncodingve Windows varsayılanı gibi eşleşen bir değere ayarlanır WindowsANSI.

±0=0
±n_:=n-±±±(n-1)

Bu, bir tekli operatörü tanımlar ±.


Ne ± ya da nasıl çalışır açıklar mısınız? Btw, 100k için tebrikler.
DavidC

1
@DavidC Teşekkürler. :) Bu sadece kullanılmayan işlev için kısayol olan yerleşik bir operatör PlusMinus. Ayrıntılar için bu gönderiye bakın.
Martin Ender

1
Çok ilginç. İle dağıtır @veya [ ]çok.
DavidC

9

J, 14 12 bayt

-$:^:3@<:^:*

@ Leaky Nun sayesinde 2 bayt tasarruf etti .

Yinelemeli zaman kendisini arayarak sonucu hesaplar n ile> 0 üç kez n 1 ve o sonucu çıkarılarak n . Temel durum için n = 0 olduğunda farklı bir durum vardır. Orada n - n'yi hesaplar, bu da 0'a eşittir.

a(n) = n - n = 0           if n = 0
       n - a(a(a(n-1)))    if n > 0

Burada deneyin.

açıklama

-$:^:3@<:^:*  Input: n
           *  Get the sign of n (n = 0 => 0, n > 0 => 1)
         ^:   Execute that many times
                (0 times means it will just be an identity function)
       <:       Decrement n
 $:             Call itself recursively
   ^:3          three times
      @         on n-1
-             Subtract that result from n and return

Parantezlerin gerekli olduğunu düşünmüyorum.
Leaky Nun

6

Julia, 16 bayt

!n=n>0&&n-!!!~-n

Çevrimiçi deneyin!

Nasıl çalışır

Tekli operatörü !amacımız için yeniden tanımlıyoruz .

Eğer n = 0 , karşılaştırma n>0döner sahte ve yapar !.

Aksi takdirde, sonraki kod &&yürütülür. ikisinin tamamlayıcısı ~-nile eşdeğerdir (n-1), !!!yinelemeli !olarak n - 1'i üç kez çağırır ve elde edilen değer n'den çıkarılır .


Bir açıklama eklemek ister misiniz? -!!~-._ ile neler olduğu hakkında hiçbir fikrim yok .
Downgoat

1
Hiçbir şey fantezi. !sadece işlevin adıdır.
Dennis

5

Python, 31 bayt

a=lambda n:n and n-a(a(a(n-1)))

Özyineleme sınırı ve zaman kısıtlamaları yukarıdaki işlevi kullanışsız hale getirir, ancak teoride çalışması gerekir (ve küçük n için çalışır).


4

JavaScript (ES6), 52 bayt

n=>[0,...Array(n)].reduce((p,_,i,a)=>a[i]=i-a[a[p]])

Sıkıcı olabilir ve özyinelemeli sürümü yazmış olabilirim ama bu sürüm çok daha hızlı (son test vakası ile kolayca başa çıkma) ve ayrıca reducebu bir artı!




3

R, 42 41 bayt

a=function(n)ifelse(n<1,0,n-a(a(a(n-1))))

Kullanımı:

> a(1)
1
> a(10)
7

Bu özyinelemeli yaklaşım, daha büyük değerler için iyi ölçeklenmez n.


Durumunuzu olarak değiştirirseniz, bir bayt (ve hatalı girdilerle birlikte bir dizi hata) kaybedebilmeniz gerekir n<1. Onun bir sırası olarak, sadece negatif olmayan tamsayılar için gerçekten tanımlanmıştır.
user5957401

a=function(n)"if"(n,n-a(a(a(n-1))),0)birkaç bayt kapalı çalışır.
Giuseppe

3

Oasis , 6 bayt

Kod:

nbaa-0

Genişletilmiş sürüm:

a(n) = nbaa-
a(0) = 0

Kod:

n      # Push n
 b     # Calculate a(n - 1)
  a    # Calculate a(a(n - 1))
   a   # Calculate a(a(a(n - 1)))
    -  # Subtract a(a(a(n - 1))) from n

Çevrimiçi deneyin!


2

Sesos , 58 55 bayt

0000000: 16e0d7 bdcdf8 8cdf1b e6cfbb 840d3f bf659b 38e187  ..............?.e.8..
0000015: f8639b 39dc37 fc893f 666c05 7e7ed9 b88b3f ae0d3f  .c.9.7..?fl.~~...?..?
000002a: 676ed8 bd9940 7fdc3b 36619e f1                    gn...@..;6a..

400'e kadar girişi gayet iyi işler, ancak çalışma süresi bu noktadan sonra önemli ölçüde artar.

Çevrimiçi deneyin! Oluşturulan SBIN kodunu görmek için Hata Ayıklamayı kontrol edin .

Sesos montajı

Yukarıdaki ikili dosya, aşağıdaki SASM kodu birleştirilerek oluşturulmuştur.

set numin, set numout

get
jmp
    jmp
        rwd 3, add 1, rwd 1, add 1, fwd 4, sub 1
    jnz
    rwd 3, sub 1
jnz
rwd 3, add 1, fwd 2
jmp
    rwd 1, sub 1, fwd 3, sub 1, fwd 2, add 3
    jmp
        rwd 2
        jmp
            rwd 3
        jnz
        fwd 6, get, rwd 4, sub 1
        jmp
            fwd 1, sub 1
            jmp
                rwd 3
            jnz
            sub 1
            jmp
                fwd 3
            jnz
            rwd 4, sub 1
        jnz
        fwd 1
        jmp
            rwd 1, add 1, fwd 1, add 1
        jnz
        sub 1, fwd 3, sub 1
        jmp
            fwd 3
        jnz
        rwd 1, sub 1
    jnz
    rwd 2, get
    nop
        rwd 3
    jnz
    fwd 3, get, rwd 2
    jmp
        fwd 2, add 1
        jmp
            fwd 3
        jnz
        rwd 1, add 1, rwd 2
        jmp
            rwd 3
        jnz
        fwd 1, sub 1
    jnz
    fwd 2
    jmp
        rwd 2, add 1, fwd 2, sub 1
    jnz
    nop
        get, fwd 3
    jnz
    rwd 1, add 1, fwd 2
jnz
rwd 2, sub 1
jmp
    rwd 1, sub 1, fwd 1, sub 1
jnz
rwd 1, put

2

LISP, 61 bayt

(defun H(N)(if(= N 0)(return-from H 0)(- N(H(H(H(- N 1)))))))

Muhtemelen en uygun çözüm değil, ama işe yarıyor.


1

Java 7, 42 bayt

int c(int n){return n>0?n-c(c(c(n-1))):0;}

Test edilmemiş ve test durumları:

Burada deneyin.

class Main{
  static int c(int n){
    return n > 0
              ? n - c(c(c(n-1)))
              : 0;
  }

  public static void main(String[] a){
    for(int i = 0; i < 21; i++){
      System.out.println(i + ": " + c(i));
    }
    System.out.println("1000: " + c(1000));
  }
}

Çıktı:

0: 0
1: 1
2: 1
3: 2
4: 3
5: 4
6: 4
7: 5
8: 5
9: 6
10: 7
11: 7
12: 8
13: 9
14: 10
15: 10
16: 11
17: 12
18: 13
19: 13
20: 14
 (last case takes too long..)

1

Yakut, 27 bayt

Bariz uygulama.

a=->n{n<1?0:n-a[a[a[n-1]]]}

Bu, dizideki önceki girişleri önbelleğe alan daha uzun ve daha hızlı bir yanıttır. Her iki cevap da 1.9'dan sonraki sürümler için işe yarıyor, o zaman ->, stabby lambda, Ruby ile tanıştı.

->n{r=[0];i=0;(i+=1;r<<i-r[r[r[i-1]]])while i<n;r[n]}



1

C 35 32 bayt

@PeterTaylor sayesinde 3 bayt tasarruf edildi!

a(n){return n?n-a(a(a(n-1))):0;}

Ideone üzerinde deneyin!


2
C'de bir tamsayıyı doğrudan koşullu olarak kullanabilirsiniz, üç baytlık bir tasarruf sağlar:a(n){return n?n-a(a(a(n-1))):0;}
Peter Taylor

1
@betseg - Kodunuzda da hatalı var :. Sonrasını çıkarmalısın ?.
owacoder

1

Javascript ES6, 22 bayt

a=n=>n&&n-a(a(a(n-1)))

Sıkıcı olacağım ve özyinelemeli versiyonu yapacağım: P


1

VBA, 69 bayt

Function H(N):ReDim G(N):For j=1To N:G(j)=j-G(G(G(j-1))):Next:H=G(N)

Test setindeki bir göz açıp kapayıncaya kadar çalışır, n = 1000000'ün biraz üzerinde yavaşlar, n = 25 milyonun biraz üzerinde bir hafıza duvarına girer.


1

Pyth, 10 bayt

L-WbbyFtb3

Bir işlevi tanımlar y. Çevrimiçi deneyin: Gösteri

Bu, Pyth'in göreceli yeni bir özelliğini kullanır. Katlama sözdizimini kullanarak bir işlevi birden çok kez uygulayabilirsiniz. Aslında herhangi bir bayt kaydetmez, sadece gösterim amaçlı kullandım.

Açıklama:

L-WbbyFtb3
L            define function y(b), that returns:
    b           b
 -Wb            and subtract the following if b>0
     yF  3      y applied three times to
       tb       b - 1

1

Akçaağaç, 28 26 bayt

`if`(n=0,0,n-a(a(a(n-1))))

Kullanımı:

> a:=n->ifelse(n=0,0,n-a(a(a(n-1))));
> seq(a(i),i=0..10);
0, 1, 1, 2, 3, 4, 4, 5, 5, 6, 7

1

dc, 34 bayt

dsn[zdddd1-;a;a;a-r:aln!=L]dsLx;ap

Giriş yığının üstünden alınır. Yığın derinliği sayaç olarak kullanıldığından, bu, yığındaki tek öğe olmalıdır. Kullanım örneği:

$ dc
10000dsn[zdddd1-;a;a;a-r:aln!=L]dsLx;ap

Bu, dizi tanımının oldukça basit bir uygulamasıdır:

dsn               # Store n as `n', and keep a copy as a depth buffer (see below)
[                 # Open loop definition
 z                # Push stack depth i for i-th term
 dddd             # Duplicate stack depth four times, for a total of five copies
 1-               # Get i-1 for use as index to previous term
                  #   Note that if we hadn't duplicated n above, or left something else
                  #   on the stack, 0-1 would be -1, which is not a valid array index
 ;a;a;a           # Fetch a(a(a(i-1)))
 -                # Calculate i-a(a(a(i-1)))
 r                # Arrange stack to store i-th term: TOS |  i  (i-a(a(a(i-1))))
 :a               # Store i-th term in array `a'
 ln!=L            # Load n. If n!=i, we're not done calculating terms yet, so execute loop
]                 # Close loop definition. Note that we started with five copies of i:
                  #   i-1 was used to get last term
                  #   i-a(...) was used to calculate current term
                  #   ... i :a was used to store current term
                  #   i ln !=L was used to check loop exit condition
                  # One copy of i is left on the stack to increment counter
dsLx              # Duplicate loop macro, store it, and execute copy
;a                # Last i stored on stack from loop will equal n, so use this to get a(n)
p                 # Print a(n)

Her neyse, açık bir şekilde başladı ... sonra golf oldu.



1

C ++ (esas olarak MSVC)

Normal sürüm: 40 bayt

int a(int n){return n?n-a(a(a(n-1))):0;}

Şablon meta programlama sürümü: 130 bayt

#define C {constexpr static int a(){return
template<int N>struct H C N-H<H<H<N-1>::a()>::a()>::a();}};template<>struct H<0>C 0;}};

Kullanımı:

std::cout << a(20) << '\n';       // Normal version
std::cout << H<20>::a() << '\n';  // Template version

Hiçbir şey optimizasyonu ile> = daha hızlı bir kayıt içine bir değer taşımaktan daha var çünkü şablon sürümü, en hızlı kodudur H<20>::a()olarak derleme:

mov esi, 14

10000 için, özyinelemeli sürüm bir yığın taşması hatası nedeniyle çöker ve şablon sürümü derleme zamanında şablon örnekleme derinliği nedeniyle çöker. GCC 900'e gidiyor (614)


Bence şablon meta programlama sürümü arasında Cve {arasında boşluk gerekmez
Zacharý

@ Zacharý MSVC bu alan olmadan derlemeyi reddediyor
HatsuPointerKun

Ahh, şimdi neden devam ettiğini görüyorum
Zacharý

@ Zacharý Makro tipine bağlıdır. Parametreleri varsa, o zaman alanı kaldırabilirim, ama burada değil
HatsuPointerKun


1

APL (Dyalog Unicode) , 18 17 bayt

{⍵=0:0⋄⍵-∇⍣3⊢⍵-1}

Çevrimiçi deneyin!

Şaşırtıcı bir şekilde, bu zorluğa APL yanıtı yok. Bu OP'deki fonksiyonun gerçek bir uygulamasıdır.

TIO zaman aşımına uğradı n>90.

@ Zacharý sayesinde bayt kurtardı.


1
{⍵=0:0⋄⍵-∇⍣3⊢⍵-1}
Zacharý


0

PowerShell v2 +, 56 bayt

$a={$n=$args[0];if($n){$n-(&$a(&$a(&$a($n-1))))}else{0}}

Özyinelemeli tanım oluşturmak için lambda'nın PowerShell eşdeğeri. &Çağrı operatörü aracılığıyla gerçekleştirin , örn &$a(5). Çalıştırılması uzun zaman alıyor - 50makinemde bile (8GB RAM'li yeni bir i5) yaklaşık 90 saniye sürüyor.

Daha hızlı yinelemeli çözüm, 59 bayt

param($n)$o=,0;1..$n|%{$o+=$_-$o[$o[$o[$_-1]]]};$o[-1]*!!$n

Daha uzun Sadece biz girişi için hesaba gerek çünkü 0(bu sayı *!!$nsonunda). Aksi takdirde, diziyi yineleyerek $n, her seferinde yeni bir öğe ekleyerek ve sonuncuyu sondan çıkarırız $o[-1]. Süper hızlı - Makinemde hesaplama 10000yaklaşık 5 saniye sürer.


0

> <> , 55 + 2 = 57 bayt

^~n;
.~-]{:0$
v>1-}32[
v/  /:1-32[
>$:?/$~]{:0$.
/30@2[

Girdinin program başlangıcında yığınta bulunması beklenir, bu nedenle -vbayrak için +2 bayt . Çevrimiçi deneyin!

Sonucu hesaplamak için özyineleme kullandığından, bu hecka yavaştır. TIO'yu kullanmak h(50)bir dakikanızı alır. Doğru sonuçları <= 30 döndürür, bu yüzden işe yarayacağından eminim h(10000), bulmak için çalıştırmadım!

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.