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


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!


(f$f$f$n-1)= f(f$f$n-1)speichert ein Byte.
Anders Kaseorg


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


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

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 .


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


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!




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.


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!


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

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.


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

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]}



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!


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


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.


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

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

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.



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)


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.


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


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.


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!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.