Séquence H de Hofstadter


15

Définition

  • a(0) = 0
  • a(n) = n-a(a(a(n-1))) pour entier n > 0

Tâche

Étant donné un entier non négatif n, sortie a(n).

Cas de test

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

Les références


Défis liés aux séquences de Hofstadter: 1 , 2 , 3
Martin Ender

4
Et je pense toujours que vous devriez faire référence à GEB ...
Martin Ender

1
En quoi la théorie des nombres est -elle pertinente ici?
flawr

1
@flawr facepalm Permettez-moi d'essayer à nouveau: Gödel, Escher, Bach: An Eternal Golden Braid
Stig Hemmer

1
@StigHemmer En fait, facepalm a maintenant son propre Emoji: 🤦
Tobias Kienzler

Réponses:


20

Haskell, 23 22 octets

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

Utilise simplement la définition de la séquence. f(f$f$n-1)est équivalent à f (f (f (n-1))).

Tester:

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]

Merci à Anders Kaseorg pour un octet!


(f$f$f$n-1)= f(f$f$n-1)enregistre un octet.
Anders Kaseorg


9

Mathematica, 20 octets

Le nombre d'octets suppose un codage ISO 8859-1 (ou compatible) et $CharacterEncodingdéfini sur une valeur correspondante, comme la valeur par défaut de Windows WindowsANSI.

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

Ceci définit un opérateur unaire ±.


Pourriez-vous expliquer ce que ± fonctionne ou comment cela fonctionne? Btw, félicitations pour 100k.
DavidC

1
@DavidC Merci. :) C'est juste un opérateur intégré qui est un raccourci pour la fonction inutilisée PlusMinus. Voir cet article pour plus de détails.
Martin Ender

1
Très intéressant. Se passe du @ou du [ ]trop.
DavidC

9

J, 14 12 octets

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

Enregistré 2 octets grâce à @ Leaky Nun .

Calcule le résultat en s'appelant récursivement lorsque n > 0 trois fois sur n -1 et en soustrayant ce résultat de n . Il y a une situation différente pour le cas de base lorsque n = 0. Là, il calcule n - n qui est égal à 0.

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

Essayez-le ici.

Explication

-$:^: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

Je ne pense pas que les parenthèses soient nécessaires.
Leaky Nun

6

Julia, 16 octets

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

Essayez-le en ligne!

Comment ça fonctionne

Nous redéfinissons l'opérateur unaire !pour nos besoins.

Si n = 0 , la comparaison n>0renvoie faux et il en va de même !.

Sinon, le code après &&est exécuté. ~-nest équivalent à (n-1)en complément à deux, !!!appelle récursivement !trois fois sur n - 1 , et la valeur résultante est soustraite de n .


Vous voulez ajouter une explication? Je n'ai aucune idée de ce qui se passe avec -!!~-._.
Downgoat

1
Rien d'extraordinaire. !est simplement le nom de la fonction.
Dennis

5

Python, 31 octets

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

La limite de récursivité et les contraintes de temps rendent la fonction ci-dessus peu pratique, mais en théorie, cela devrait fonctionner (et fonctionne pour les petits n).


4

JavaScript (ES6), 52 octets

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

J'aurais pu être ennuyeux et avoir écrit la version récursive mais cette version est beaucoup plus rapide (en faisant facilement face au dernier cas de test) et utilise aussi reducedonc c'est un plus!



3

CJam, 13 12 octets

Merci à Dennis d'avoir économisé 1 octet.

ri0{_(jjj-}j

Testez-le ici.


Cela fonctionne pour des valeurs étonnamment élevées. Je pense que vous n'en avez pas besoin a.
Dennis

@Dennis Oh, c'est bon à savoir, merci.
Martin Ender

3

R, 42 41 octets

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

Usage:

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

Cette approche récursive n'est pas adaptée à des valeurs plus importantes n.


Vous devriez pouvoir perdre un octet (et un certain nombre d'erreurs avec de mauvaises entrées) si vous changez votre condition en n<1. Comme c'est une séquence, elle n'est de toute façon vraiment définie que pour les entiers non négatifs.
user5957401

a=function(n)"if"(n,n-a(a(a(n-1))),0)fonctionnera pendant plusieurs octets.
Giuseppe

3

Oasis , 6 octets

Code:

nbaa-0

Version étendue:

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

Essayez-le en ligne!


2

Sesos , 58 55 octets

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

Gère jusqu'à 400 entrées raisonnablement bien, mais le temps d'exécution augmente considérablement après ce point.

Essayez-le en ligne! Vérifier le débogage pour voir le code SBIN généré.

Assemblage Sesos

Le fichier binaire ci-dessus a été généré en assemblant le code SASM suivant.

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 octets

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

Probablement pas la solution optimale, mais cela fonctionne.


1

Java 7, 42 octets

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

Cas non testés et testés:

Essayez-le ici.

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

Production:

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

Rubis, 27 octets

La mise en œuvre évidente.

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

Il s'agit d'une réponse plus longue et plus rapide qui met en cache les entrées précédentes de la séquence. Les deux réponses ne fonctionnent que pour les versions après 1.9, car c'est à ce moment ->-là que la stabby lambda a été présentée à Ruby.

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


1

Golfscript, 26 25 octets

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

Essayez-le en ligne!

Localement 10000prend moins d'une demi-seconde.


1

C, 35 32 octets

Sauvegardé 3 octets grâce à @PeterTaylor!

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

Essayez-le sur Ideone!


2
En C, vous pouvez utiliser un entier directement comme conditionnel, ce qui donne une économie de trois octets:a(n){return n?n-a(a(a(n-1))):0;}
Peter Taylor

1
@betseg - Vous avez également une erreur :dans votre code. Vous devez retirer celui qui suit ?.
owacoder

1

Javascript ES6, 22 octets

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

Je vais être ennuyeux et faire la version récursive: P


1

VBA, 69 octets

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

Fonctionne en un clin d'œil sur l'ensemble de test, ralentit un peu au-dessus de n = 1000000, se heurte à un mur de mémoire un peu supérieur à n = 25 millions.


1

Pyth, 10 octets

L-WbbyFtb3

Définit une fonction y. Essayez-le en ligne: Démonstration

Cela utilise une nouvelle fonctionnalité relative de Pyth. Vous pouvez appliquer une fonction plusieurs fois à l'aide de la syntaxe de pliage. Il n'enregistre en fait aucun octet, je l'ai utilisé uniquement à des fins de démonstration.

Explication:

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

Érable, 28 26 octets

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

Usage:

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

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

L'entrée provient du haut de la pile. Ce doit être le seul élément de la pile, car la profondeur de la pile est utilisée comme compteur. Exemple d'utilisation:

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

Il s'agit d'une implémentation assez simple de la définition de séquence:

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)

Quoi qu'il en soit, cela a commencé simplement ... puis le golf s'est produit.



1

C ++ (MSVC, principalement)

Version normale: 40 octets

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

Version de programmation de méta modèle: 130 octets

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

Utilisation:

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

La version du modèle est le code le plus rapide, car il n'y a rien de plus rapide que de déplacer une valeur dans un registre => avec optimisation, H<20>::a()compiler comme:

mov esi, 14

Pour 10000, la version récursive se bloque en raison d'une erreur de dépassement de pile et la version du modèle se bloque au moment de la compilation en raison de la profondeur d'instanciation du modèle. GCC passe à 900 (614)


Je pense que vous n'avez pas besoin de l'espace entre Cet {dans la version de programmation de méta modèle
Zacharý

@ Zacharý MSVC refuse de compiler sans cet espace
HatsuPointerKun

Ahh, je vois maintenant pourquoi cela semble continuer
Zacharý

@ Zacharý Cela dépend du type de macro. S'il a des paramètres, alors je peux supprimer l'espace, mais ici ce n'est pas le cas
HatsuPointerKun


1

APL (Dyalog Unicode) , 18 17 octets

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

Essayez-le en ligne!

Étonnamment, il n'y a pas de réponse APL à ce défi. Il s'agit d'une implémentation littérale de la fonction dans l'OP.

TIO expire pour n>90.

Un octet enregistré grâce à @ Zacharý.


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


0

PowerShell v2 +, 56 octets

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

L'équivalent PowerShell d'un lambda pour former la définition récursive. Exécutez-le via l' &opérateur d'appel, par exemple &$a(5). L' exécution prend beaucoup de temps - même 50sur ma machine (un i5 récent avec 8 Go de RAM) prend environ 90 secondes.

Solution itérative plus rapide, 59 octets

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

Plus longtemps seulement parce que nous devons tenir compte de l'entrée 0(c'est *!!$nla fin). Sinon, nous construisons simplement le tableau de manière itérative jusqu'à $n, en ajoutant un nouvel élément à chaque fois, et en sortant le dernier à la fin $o[-1]. Super rapide - le calcul 10000sur ma machine prend environ 5 secondes.


0

> <> , 55 + 2 = 57 octets

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

L'entrée devrait être présente sur la pile au démarrage du programme, donc +2 octets pour l' -vindicateur. Essayez-le en ligne!

C'est très lent, car il utilise la récursivité pour calculer le résultat. L'utilisation de TIO h(50)prend plus d'une minute. Il renvoie les résultats corrects <= 30, donc je suis sûr que cela fonctionnerait h(10000), je ne l'ai pas exécuté pour le savoir!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.