Hofstadter H-Sequenz

15

Definition

  • a(0) = 0
  • a(n) = n-a(a(a(n-1))) für ganze Zahl n > 0

Aufgabe

Bei nicht negativer Ganzzahl nwird ausgegeben a(n).

Testfälle

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

Verweise

Undichte Nonne
quelle
Verwandte Herausforderungen bei Hofstadter-Sequenzen: 1 , 2 , 3
Martin Ender
4
Und ich denke immer noch, Sie sollten GEB verweisen ...
Martin Ender
1
Wie ist die Zahlentheorie hier relevant?
Fehler
1
@flawr facepalm Lassen Sie mich versuchen , dass wieder: Gödel, Escher, Bach: Ein Ewiges goldenes Braid
Stig Säumer
1
@StigHemmer Tatsächlich hat facepalm
Tobias Kienzler

Antworten:

20

Haskell, 23 22 Bytes

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

Verwendet einfach die Definition der Reihenfolge. f(f$f$n-1)ist äquivalent zu f (f (f (n-1))).

Prüfung:

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]

Vielen Dank an Anders Kaseorg für ein Byte!

Türknauf
quelle
(f$f$f$n-1)= f(f$f$n-1)speichert ein Byte.
Anders Kaseorg
9

Gelee , 8 Bytes

’ßßßạµṠ¡

Probieren Sie es online! oder überprüfen Sie die kleineren Testfälle .

Wie es funktioniert

’ßßßạµṠ¡  Main link. Argument: n

     µṠ¡  Execute the preceding chain sign(n) times.
’         Decrement n, yielding n - 1.
 ßßß      Recursively call the main link thrice.
    ạ     Take the absolute difference of n and the result.
Dennis
quelle
9
Kann der Jelly-Parser auch Programme verarbeiten, die größer als 10 Byte sind?
Steenbergh
9

Mathematica, 20 Bytes

Die Byteanzahl setzt die ISO 8859-1-Codierung (oder eine kompatible Codierung) voraus und wird $CharacterEncodingauf einen übereinstimmenden Wert festgelegt, wie in der Windows-Standardeinstellung WindowsANSI.

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

Dies definiert einen unären Operator ±.

Martin Ender
quelle
Würden Sie erklären, was ± macht oder wie es funktioniert? Übrigens, herzlichen Glückwunsch zu 100k.
DavidC
1
@ DavidC Danke. :) Es ist nur ein eingebauter Operator, der die nicht verwendete Funktion abkürzt PlusMinus. Siehe diesen Beitrag für Details.
Martin Ender
1
Sehr interessant. Verzichtet auf das @oder [ ]auch.
DavidC
9

J, 14-12 Bytes

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

2 Bytes dank @ Leaky Nun gespeichert .

Ermittelt das Ergebnis durch den Aufruf selbst rekursiv , wenn n > 0 dreimal auf n -1 und dieses Ergebnis aus der Subtraktion n . Anders sieht es im Basisfall aus, wenn n = 0 . Dort wird n - n berechnet , was 0 entspricht.

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

Probieren Sie es hier aus.

Erläuterung

-$:^: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
Meilen
quelle
Ich denke nicht, dass die Klammern benötigt werden.
Undichte Nonne
6

Julia, 16 Bytes

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

Probieren Sie es online!

Wie es funktioniert

Wir definieren den unären Operator !für unsere Zwecke neu.

Wenn n = 0 , der Vergleichn>0 kehrt falsch und so tut !.

Andernfalls wird der Code danach &&ausgeführt. ~-nentspricht (n-1)dem Zweierkomplement, !!!ruft rekursiv !dreimal n - 1 auf und der resultierende Wert wird von n subtrahiert .

Dennis
quelle
Möchtest du eine Erklärung hinzufügen? Ich habe keine Ahnung, was mit -!!~-._ los ist.
Downgoat
1
Nichts Besonderes. !ist einfach der Name der Funktion.
Dennis
5

Python, 31 Bytes

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

Rekursionsgrenze und Zeitbeschränkungen machen die obige Funktion unpraktisch, aber theoretisch sollte sie funktionieren (und funktioniert für kleine n).

orlp
quelle
4

JavaScript (ES6), 52 Byte

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

Ich hätte langweilig sein und die rekursive Version schreiben können, aber diese Version ist viel schneller (leicht mit dem letzten Testfall fertig zu werden) und verwendet sie auch reduce, also ist das ein Plus!

Neil
quelle
3

CJam, 13 12 Bytes

Vielen Dank an Dennis für das Speichern von 1 Byte.

ri0{_(jjj-}j

Teste es hier.

Martin Ender
quelle
Das funktioniert für überraschend hohe Werte. Ich denke du brauchst das nicht a.
Dennis
@Dennis Oh, das ist gut zu wissen, danke.
Martin Ender
3

R, 42 41 Bytes

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

Verwendung:

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

Dieser rekursive Ansatz ist für größere Werte von nallerdings nicht gut skalierbar.

DSkoog
quelle
Sie sollten in der Lage sein, ein Byte (und eine Reihe von Fehlern mit fehlerhaften Eingaben) zu verlieren, wenn Sie Ihre Bedingung in ändern n<1. Als Folge ist es ohnehin nur für nicht negative ganze Zahlen wirklich definiert.
user5957401
a=function(n)"if"(n,n-a(a(a(n-1))),0)funktioniert für mehrere Bytes aus.
Giuseppe
3

Oase , 6 Bytes

Code:

nbaa-0

Erweiterte Version:

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

Code:

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

Probieren Sie es online!

Adnan
quelle
2

Sesos , 58 55 Bytes

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..

Behandelt Eingaben bis zu 400 ziemlich gut, aber die Laufzeit steigt danach dramatisch an.

Probieren Sie es online! Überprüfen Sie Debug , um den generierten SBIN-Code anzuzeigen.

Sesos Montage

Die obige Binärdatei wurde durch Zusammenstellen des folgenden SASM-Codes generiert.

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
Dennis
quelle
2

LISP, 61 Bytes

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

Wahrscheinlich nicht die optimale Lösung, aber es funktioniert.

Ästhet
quelle
1

Java 7, 42 Bytes

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

Ungolfed & Testfälle:

Probieren Sie es hier aus.

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));
  }
}

Ausgabe:

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..)
Kevin Cruijssen
quelle
1

Ruby, 27 Bytes

Die offensichtliche Umsetzung.

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

Dies ist eine längere und schnellere Antwort, mit der vorherige Einträge in der Sequenz zwischengespeichert werden. Beide Antworten funktionieren nur für Versionen nach 1.9, als ->das Stabby Lambda in Ruby eingeführt wurde.

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

C #, 35 Bytes

int a(int n)=>n>0?n-a(a(a(n-1))):0;
TheLethalCoder
quelle
1

Golfscript, 26 25 Bytes

~ [0] {...., (=== \., @ - +} @ *) \;
~ [0] {...) \; == \., @ - +} @ *) \;

Probieren Sie es online!

Vor Ort 10000dauert weniger als eine halbe Sekunde.

Undichte Nonne
quelle
1

C, 35 32 Bytes

3 Bytes gespart dank @PeterTaylor!

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

Probieren Sie es auf Ideone!

betseg
quelle
2
In C können Sie eine Ganzzahl direkt als Bedingung verwenden, was eine Einsparung von drei Bytes ergibt:a(n){return n?n-a(a(a(n-1))):0;}
Peter Taylor,
1
@betseg - Sie haben auch einen Fehler :in Ihrem Code. Sie sollten den nachher herausnehmen ?.
Owacoder
1

Javascript ES6, 22 Bytes

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

Ich werde langweilig sein und die rekursive Version machen: P

Mama Fun Roll
quelle
1

VBA, 69 Bytes

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

Arbeitet im Handumdrehen auf dem Test-Set, verlangsamt sich etwas oberhalb von n = 1000000, stößt auf eine Speicherwand etwas oberhalb von n = 25 Millionen.

Joffan
quelle
1

Pyth, 10 Bytes

L-WbbyFtb3

Definiert eine Funktion y. Probieren Sie es online aus: Demonstration

Dies nutzt eine relativ neue Funktion von Pyth. Mit der Fold-Syntax können Sie eine Funktion mehrfach anwenden. Es speichert eigentlich keine Bytes, ich habe es nur zu Demonstrationszwecken verwendet.

Erläuterung:

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
Jakube
quelle
1

Ahorn, 28 26 Bytes

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

Verwendung:

> 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
DSkoog
quelle
1

Gleichstrom, 34 Bytes

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

Die Eingabe erfolgt vom oberen Rand des Stapels. Dies muss das einzige Element auf dem Stapel sein, da die Stapeltiefe als Zähler verwendet wird. Anwendungsbeispiel:

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

Dies ist eine ziemlich einfache Implementierung der Sequenzdefinition:

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)

Wie auch immer, es begann einfach ... dann geschah das Golfen.

Joe
quelle
1

C ++ (hauptsächlich MSVC)

Normale Version: 40 Bytes

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

Template Meta-Programmierversion: 130 Bytes

#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;}};

Verwendung :

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

Die Template-Version ist der schnellste Code, da es nichts schnelleres gibt, als einen Wert in ein Register zu verschieben => mit Optimierung H<20>::a()kompilieren Sie als:

mov esi, 14

Bei 10000 stürzt die rekursive Version aufgrund eines Stapelüberlauffehlers ab, und die Vorlagenversion stürzt zur Kompilierungszeit aufgrund der Tiefe der Vorlageninstanziierung ab. GCC geht an 900 (614)

HatsuPointerKun
quelle
Ich denke, Sie brauchen nicht das Leerzeichen zwischen Cund {in der Vorlage Meta-Programmierversion
Zacharý
@ Zacharý MSVC weigert sich, ohne dieses Leerzeichen zu kompilieren
HatsuPointerKun
Ahh, ich verstehe jetzt, warum das so zu bleiben scheint
Zacharý
@ Zacharý Es kommt auf die Art des Makros an. Wenn es Parameter hat, dann kann ich das Leerzeichen entfernen, aber hier nicht
HatsuPointerKun
1

APL (Dyalog Unicode) , 18 bis 17 Bytes

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

Probieren Sie es online!

Überraschenderweise gibt es keine APL-Antwort auf diese Herausforderung. Dies ist eine wörtliche Implementierung der Funktion im OP.

TIO hat eine Auszeit für n>90.

Dank @ Zacharý ein Byte gespeichert.

J. Sallé
quelle
1
{⍵=0:0⋄⍵-∇⍣3⊢⍵-1}
Zacharý
0

Python 3, 72 Bytes

def f(n):
    a=[0];i=0
    while n:i+=1;a+=[i-a[a[a[i-i]]]];n-=1
    return a[i]

Ideone es!

Undichte Nonne
quelle
0

PowerShell v2 +, 56 Byte

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

Das PowerShell-Äquivalent eines Lambdas zur Bildung der rekursiven Definition. Führen Sie es über den &Call Operator aus, z &$a(5). Die Ausführung dauert sehr lange - selbst 50auf meinem Computer (einem neuen i5 mit 8 GB RAM) dauert die Ausführung ungefähr 90 Sekunden.

Schnellere iterative Lösung, 59 Bytes

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

Nur länger, weil wir Eingaben berücksichtigen müssen 0(das ist *!!$ndas Ende). Ansonsten konstruieren wir das Array nur iterativ bis $n, fügen jedes Mal ein neues Element hinzu und geben das letzte am Ende aus $o[-1]. Superschnell - das Rechnen 10000auf meiner Maschine dauert ungefähr 5 Sekunden.

AdmBorkBork
quelle
0

> <> , 55 + 2 = 57 Bytes

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

Es wird erwartet, dass die Eingabe beim Programmstart auf dem Stack vorhanden ist, also +2 Byte für das -vFlag. Probieren Sie es online!

Dies ist hecka langsam, da es die Rekursion verwendet, um das Ergebnis zu berechnen. Die Verwendung von TIO h(50)dauert mehr als eine Minute. Es gibt die korrekten Ergebnisse <= 30 zurück, daher bin ich zuversichtlich, dass es funktionieren würde. Ich habe es h(10000)nur nicht ausgeführt, um es herauszufinden!

Sok
quelle