Générer la séquence de Recamán


20

La séquence de Recamán ( A005132 ) est une séquence mathématique, définie comme telle:

A(0) = 0
A(n) = A(n-1) - n if A(n-1) - n > 0 and is new, else
A(n) = A(n-1) + n

Une jolie version LaTex de ce qui précède (pourrait être plus lisible):

A(n)={0if n=0A(n1)nif A(n1)n is positive and not already in the sequenceA(n1)+notherwise

Les premiers termes sont 0, 1, 3, 6, 2, 7, 13, 20, 12, 21, 11

Pour clarifier, is newsignifie si le nombre est déjà dans la séquence.

Étant donné un entier n, via l'argument de fonction ou STDIN, retournez les premiers ntermes de la séquence Recamán.


C'est un défi de code-golf, donc le code le plus court gagne.


Que signifie «nouveau»?
Beta Decay

Si un nombre est nouveau, cela signifie qu'il n'est pas encore dans la séquence. Je viens de réaliser que j'ai mal tapé la séquence, donnez-moi une minute pour la corriger.
James Williams

Correction de la séquence.
James Williams

1
Pouvez-vous ajouter les premières valeurs de la séquence?
fier haskeller

Ajout des premiers chiffres! (Et un lien vers sa page OEIS)
James Williams

Réponses:


9

CJam, 34 33 octets

0ali{_W=_I-__0<4$@#)|@I+@?+}fI1>`

Essayez-le en ligne.

Exemple d'exécution

$ cjam <(echo '0ali{_W=_I-__0<4$@#)|@I+@?+}fI1>`') <<< 33
[0 1 3 6 2 7 13 20 12 21 11 22 10 23 9 24 8 25 43 62 42 63 41 18 42 17 43 16 44 15 45 14 46]

Comment ça fonctionne

0ali                               " Push S := [ 0 ] and read an integer N from STDIN.    ";
    {                      }fI     " For each I in [ 0 ... (N - 1) ]:                     ";
     _W=                           "   X := S[-1].                                        ";
        _I-                        "   Y := X - I                                         ";
            _0<                    "   A := (Y < 0)                                       ";
           _   4$@#)               "   B := (Y ∊ S)                                       ";
                     @I+           "   Z := X + I                                         ";
                    |   @?         "   C := (A || B) ? Z : Y                              ";
                          +        "   S += [C]                                           ";
                              1>`  " Push str(S[1:]).                                     ";

Quel changement avez-vous fait?
Soham Chowdhury

Ma première approche a ajouté des nombres négatifs à la séquence, donc je n'ai pas eu à vérifier explicitement si A(i) - i > 0. Cependant, je n'ai pas ajouté suffisamment de nombres pour les petites valeurs de n. Maintenant, je fais exactement ce que dit la spécification.
Dennis

33 contre 45. Si proche et pourtant si loin. :)
Ingo Bürk

Wow, commentaire sans e#en Cjam ... savoureuse cerise.
Chromium

8

Haskell, 74

l=0:0#1
a§v|a<0||a`elem`r v=v|1<2=0-v
a#b=a+(a-bb:l!!b#(b+1)
r=(`take`l)

Exemple d'utilisation:

λ> r 20
[0,1,3,6,2,7,13,20,12,21,11,22,10,23,9,24,8,25,43,62]

6

Rubis, 71 70 octets

f=->n{a=[0];(n-1).times{|i|a+=[[b=a[-1]-i-1]-a!=[]&&b>0?b:b+2*i+2]};a}

Une mise en œuvre très "mot à mot" de la définition.


5

Python 2, 78 75 73 69 octets

Bravo à xnor et flornquake
Maintenant près de 10 octets de moins que la réponse initiale

m=p,=0,
exec"p+=1;k=m[-1]-p;m+=k+2*p*(k*(k>0)in m),;"*input()
print m

Vous pouvez raccourcir [k,k+2*p][bool]à k+2*p*(bool).
xnor

@xnor Merci, économisé 3 octets.
Markuz

Cela k in m or k<0peut aussi être le k*(k>=0)in mcas si k<0le produit est 0, ce qui est dedans m.
xnor

@xnor Brilliant! Merci encore
Markuz

Vous pouvez écrire à la -1place de p-1. Modifier: vous pouvez également créer mun tuple et écrire m=0,et m+=k+2*p*(k*(k>0)in m),.
flornquake du

4

Golfscript (41 45 )

Essayez-le ligne ici :

(,1,\{:~1$=~)-:^1<\.^?)!!@|^\{~)2*+}*+}/

Explication

C'est pour la solution originale de 45 octets, mais c'est à peu près la même:

(,              # push array [0 .. n-1]
[0]\            # push sequence elements as [0] and reverse stack
{               # foreach element in [0 .. n-1] do:
  :m;           # store current element in m and discard
  .m=           # get the previous sequence element
  m)-:^         # subtract the current index from it and store in ^
  0>            # is that number greater than 0?
  \.^?)!        # is that number new to our sequence?
  @&            # logically and both checks
  {^}           # if true, push ^
  {^m)2*+}      # otherwise, add the index twice and push
  if
  +             # add new element to our sequence
}/
`               # make output pretty

Edit # 1: Merci à Dennis d'avoir rasé 4 octets.


4

dc , 46 octets

sn[z+z+d0r:a]sF0[pz-d1>Fd;a0<Fddd:azln!<M]dsMx

Essayez-le en ligne!

Ce programme prend les entrées d'une pile par ailleurs vide et les sorties vers stdout (délimité par la nouvelle ligne).

Je suis vraiment fier de celui-ci - il bat tout ce qui n'est pas un langage de golf dédié et présente trois de mes trucs de golf préférés en DC:

  • Taille de pile utilisée comme variable d'index
  • Refactorisation "si A alors B sinon C" en "inconditionnellement C, et si A alors D" où C et D se combinent pour faire B
  • la fonction de tableau à accès aléatoire peu utilisée pour résoudre une contrainte d'unicité

Explication

sn             Stores the input in register n
[z+z+0r:a]sF   Defines the macro F, which: 
    z+z+         adds twice the stack size/index variable
    0r:a         resets the "uniqueness" flag to 0 in the array a
               In context, F is the "D" in my description above, 
               changing A(z-1)-z to A(z-1)+z
0              The main loop starts with the previous sequence member on top of 
               the stack and total stack depth equal to the next index. 
               Pushing a zero accomplishes both of these things.
[              Start of the main loop M
  p               Print the previous sequence member, with newline (no pop)
  z-             Calculate A(z-1)-z
  d1>F           If that's nonpositive, (F)ix it to be A(z-1)+z
  d;a            a is my array of flags to see if we've hit this value before
  0<F            If we have, (F)ix it! (nonzero = flag, since ;a is zero by
                 default, and also zero if we just (F)ixed and therefore 
                 don't care about uniqueness right now)
  ddd            Make one copy to keep and two to eat
  :a             Flag this entry as "used" in the uniqueness array a
  zln!<M         If our "index variable" is n or less, repeat!
]dsMx          End of main loop - store it and execute

c'est sauvage, je ne savais même pas que dc existait
don bright

3

JavaScript - 81 80 79 70

Félicitations à edc65 pour m'avoir aidé à économiser 9 octets

f=n=>{for(a=[x=i=0];++i<n;)a[i]=x+=x>i&a.indexOf(x-i)<0?-i:i;return a}

-9: g = n => {pour (a = [x = i = 0]; ++ i <n;) a [i] = x + = x> i & a.indexOf (xi) <0? -I: i ; retourner un}
edc65

@ edc65 Grazie mille :)
William Barbosa

3

JavaScript, ES6, 74 69 caractères

Exécutez le code ci-dessous dans la dernière console Web de Firefox.

G=n=>(i=>{for(r=[t=0];++i<n;)r[i]=t+=i>t|~r.indexOf(t-i)?i:-i})(0)||r

J'essaierai de jouer au golf plus tard.

Exemple d'utilisation:

G(11) -> 0,1,3,6,2,7,13,20,12,21,11

3

MATLAB, 83 78 octets

Enregistrez ce qui suit sous f.m(73 octets)

A=0;for i=1:n-1 b=A(i)-i;A(i+1)=b+2*i;if b>0&&~any(A==b) A(i+1)=b;end;end

Exécuter à partir de la fenêtre de commande (5 octets)

n=9;f

Si ce qui précède n'est pas légal, cela nécessite 90 octets.

function A=f(n) 
A=0;for i=1:n-1 b=A(i)-i;A(i+1)=b+2*i;if b>0&&~any(A==b) A(i+1)=b;end;end

3

R: 96 caractères

Golfé:

A=function(s,n,m,i){if(m==n){return(s)}else{t=i-m;if(t%in%s||t<0){t=i+m};s=c(s,t);A(s,n,m+1,t)}}

Non golfé:

A = function(s,n,m,i) {
    if(m==n){return(s)}
    else{
        t=i-m
        if(t%in%s||t<0){t=i+m}
        s=c(s,t)
        A(s,n,m+1,t)
    }
}

Exemple d'exécution:

> An(0,34,1)
[1]   0   1   3   6   2   7  13  20  12  21  11  22  10  23   9  24   8
[18]  25  43  62  42  63  41  18  42  17  43  16  44  15  45  14  46  79


3

Perl 6 , 62 57 octets

{(0, {$ - @ + @ * 2 * ($ !> @ || $ - @ ∈ @ ) donné @ [* -1]} ... *) [^ $ ]}

{(0,{($!=@_[*-1])+@_-@_*2*($!>@_&&$!-@_∉@_)}...*)[^$_]}

-5 octets grâce à Jo King

Essayez-le en ligne!


c'est incroyable ... on dirait que mon chat a traversé mon clavier.
don bright

3

05AB1E , 19 octets

¾ˆG¯¤N-DŠD0›*åN·*+ˆ

Essayez-le en ligne!

Explication

¾ˆ                    # Initialize the global list with 0
  G                   # for N in [1, input-1] do:
   ¯                  # push the global list
    ¤N-               # subtract N from the last item in the list
       D              # duplicate
        Š             # move the copy down 2 spots on the stack
         D            # duplicate again
          0›          # check if it is positive
            *         # multiply, turning negative results to zero
             å        # is the result already present in the list?
              N·*     # multiply by N*2
                 +    # add to the result
                  ˆ   # add this to the list

Comment cela marche-t-il?
lirtosiast

@lirtosiast: Cela fait un moment que je n'ai pas relevé ce défi, c'est donc la meilleure explication que je puisse faire à court terme. J'espère que ça suffit.
Emigna

3

K (oK) , 53 octets

Solution:

{$[y>c:#x;o[x,(r;*|x+c)(r in x)|0>r:*|x-c;y];x]}[,0;]

Essayez-le en ligne!

Explication:

Solution récursive.

{$[y>c:#x;o[x,(r;*|x+c)(r in x)|0>r:*|x-c;y];x]}[,0;] / the solution
{                                              }[,0;] / lambda with first arg set as list containing 0
 $[      ;                                  ; ]       / if[condition;true;false]
       #x                                             / length of x
     c:                                               / save as c
   y>                                                 / y greater than? (ie have we produced enough results?)
                                             x        / return x if we are done
          o[                             ;y]          / recurse with new x and existing y
                                      x-c             / subtract c from x
                                    *|                / reverse first, aka last
                                  r:                  / save result as r
                                0>                    / 0 greater than?
                               |                      / or
                       (      )                       / do together
                        r in x                        / r in x?
              ( ;     )                               / use result to index into this 2-item list
                   x+c                                / add c to x
                 *|                                   / reverse first, aka last 
               r                                      / result
            x,                                        / append to x

2

Java, 144

int[]f(int n){int[]a=new int[n];a[0]=0;int i,j,k,m;for(i=0;i<n-1;){k=a[i++]-i;m=0;for(j=0;j<i;)if(k==a[j++])m=1;a[i]=m<1&k>0?k:k+2*i;}return a;}

2

Lua - 141 135 139 135

function s(n)a,b={1},{[0]=0}for i=1,n do k=b[i-1]-i c=k+i+i if(k>0)and(a[k]==nil)then b[i],a[k]=k,1 else b[i],a[c]=c,1 end end return b end

version lisible:

function s(n)
a,b={1},{[0]=0}
for i=1,n do 
   k=b[i-1]-i 
   c=k+i+i
   if (k>0) and (a[k]==nil) then 
      b[i],a[k]=k,1 
   else 
      b[i],a[c]=c,1
   end 
end 
return b 
end

J'utilise 2 tableaux, le premier s'appelle un et il est construit de telle sorte qu'un [i] = 1 si i est déjà apparu dans la séquence, nul sinon, tandis que le second tableau contient en fait la séquence


Votre séquence devrait commencer par 0, cependant
William Barbosa

1
Vous avez raison, je n'ai pas examiné la question très attentivement et j'ai supposé qu'elle avait la même définition à mathworld (à partir de 1), je pense que cela ne coûtera plus de caractère, je le testerai et le corrigerai plus tard, J'écris depuis mon téléphone maintenant!

2

Python, 73

def f(x,t=0):
 if x:t=f(x-1);t+=2*x*(t*(t>0)in map(f,range(x)))
 return t

Edit 1: Merci aux conseils de @ xnor sur l'autre réponse Python! (Je viens de réaliser que les deux se ressemblent beaucoup.)

Edit 2: Merci encore, @xnor.


Cela donne une boucle infinie. Vous avez besoin d'une sorte de flux de contrôle pour f(x)ne pas toujours appeler immédiatement f(x-1).
xnor

@xnor a corrigé le code.
Soham Chowdhury

1
Cela semble renvoyer le nième terme, pas les n premiers termes.
Dennis

Quelques sauvegardes mineures: t=0peuvent aller en tant que paramètre facultatif fet t=t+peuvent l'être t+=.
xnor

2

Groovy: 122 118 111 111 caractères

Golfé:

m=args[0] as int
a=[0]
(1..m-1).each{n->b=a[n-1];x=b-n;(x>0&!(x in a))?a[n]=x:(a[n]=b+n)}
a.each{print "$it "}

Non golfé:

m = args[0] as int
a = [0]
(1..m-1).each { n->
    b = a[n-1]
    x = b-n
    ( x>0 & !(x in a) ) ? a[n] = x : (a[n] = b+n) 
}
a.each{print "$it "}

Exemple d'exécution:

bash$ groovy Rec.groovy 14
0 1 3 6 2 7 13 20 12 21 11 22 10 23

2

Clojure: 174 caractères

Golfé:

(defn f[m a](let[n(count a)b(last a)x(- b n)y(if(and(> x 0)(not(.contains a x)))x(+ b n))](if(= m n)a(f m(conj a y)))))(println(f(read-string(first *command-line-args*))[0]))

Non golfé:

(defn f[m a]
  (let [n (count a) 
        b (last a) 
        x (- b n) 
        y (if (and (> x 0) (not (.contains a x))) x (+ b n)) ]
    (if (= m n) a (f m (conj a y))) ) )

(println (f (read-string (first *command-line-args*)) [0]) )

Exemple d'exécution:

bash$ java -jar clojure-1.6.0.jar rec.clj 14 
[0 1 3 6 2 7 13 20 12 21 11 22 10 23]

1
Je vous suggère de ne pas lire à partir de STDIN mais de prendre simplement un argument entier à la fonction :) De plus, vous ne tirez aucun avantage de la définition ysur le letformulaire, vous pouvez utiliser l'expression directement là où la valeur est nécessaire.
NikoNyrh

2

Mathcad, 54 "octets"

entrez la description de l'image ici


Du point de vue de l'utilisateur, Mathcad est en fait un tableau blanc 2D, avec des expressions évaluées de gauche à droite, de haut en bas. Mathcad ne prend pas en charge une entrée "texte" conventionnelle, mais utilise à la place une combinaison de texte et de touches / barre d'outils / éléments de menu spéciaux pour insérer une expression, du texte, un tracé ou un composant. Par exemple, tapez ":" pour entrer l'opérateur de définition (affiché à l'écran sous la forme ": =") ou "ctl-shft- #" pour entrer l'opérateur de boucle for (y compris les espaces réservés pour la variable d'itération, les valeurs d'itération et un corps expression). Ce que vous voyez dans l'image ci-dessus est exactement ce qui apparaît sur l'interface utilisateur et comme "tapé".

À des fins de golf, le nombre "d'octets" est le nombre équivalent d'opérations au clavier requises pour entrer une expression.


C'est bien beau , mais quelles sont les frappes réelles?
Jo King


2

Stax , 19 octets

É╖C8½ΔL▄░▬L+≡ΩSa⌂¼╧

Exécuter et déboguer

Déballé, non golfé et commenté, il ressemble à ceci. Il conserve la séquence jusqu'à présent sur la pile et se souvient A(n - 1)dans le registre X. L'index d'itération est utilisé pour n. La première fois, c'est 0, mais dans cette itération, il génère le 0 sans cas particulier, il n'est donc pas nécessaire d'ajuster l'index off-by-1.

0X      push 0 to main stack and store it in X register, which will store A(n - 1)
z       push an empty array that will be used to store the sequence
,D      pop input from input stack, execute the rest of the program that many times
  xi-Y  push (x-register - iteration-index) and store it in the Y register
        this is (A(n - 1) - n)
  0>    test if (A(n - 1) - n) is greater than 0 (a)
  ny#   count number of times (A(n - 1) - n) occurs in the sequence so far (b)
  >     test if (a) > (b)
    y   (A(n - 1) - n)
    xi+ A(n - 1) + n
  ?     if/else;  choose between the two values based on the condition
  X     store the result in the X register
  Q     print without popping
  +     append to sequence array

Exécutez et déboguez celui-ci


intéressant. Comment cela marche-t-il?
don bright

1
@donbright: Ajout d'annotations et d'explications.
récursif le


2

Pyth , 24 octets

tu+G-eG_W|g0J-eGH}JGHQ]0

Essayez-le en ligne!

tu+G-eG_W|g0J-eGH}JGHQ]0   Implicit: Q=eval(input())
 u                   Q     Reduce [0-Q)...
                      ]0   ... with initial value G=[0], next value as H:
              eG             Last value of G (sequence so far)
             -  H            Take H from the above
            J                Store in J
          g0J                0 >= J
                 }JG         Is J in G?
         |                   Logical OR of two previous results
       _W           H        If the above is true, negate H, otherwise leave as positive
    -eG                      Subtract the above from last value in G
  +G                         Append the above to G
                           The result of the reduction is the sequence with an extra leading 0
t                          Remove a leading 0, implicit print

1

Powershell (103)

$n=Read-Host;$a=@(0);$n-=1;1..$n|%{$x=$a[-1]-$_;if($x-gt0-and!($a-like$x)){$a+=$x}else{$a+=$x+2*$_}};$a

Une autre implémentation «mot pour mot» ici aussi. Étonnamment lisible également pour PowerShell.

La séquence est stockée dans le tableau $ a et imprimée un terme par ligne.

Pour $ n = 20 si nous exécutons l'instruction, $a-join","nous obtenons

0,1,3,6,2,7,13,20,12,21,11,22,10,23,9,24,8,25,43,62

1

C #: 140 caractères

int i,w,t,y;int[]F(int n){var r=new int[n--];for(;i<n;y=0){w=r[i++]-i;for(t=0;y<i&&t<1;)t=w==r[y++]?1:0;r[i]=w>0&&t<1?w:r[i-1]+i;}return r;}

1

C ++: 180 caractères (158 sans instructions cin et cout)

int a[5000000][2]={0},i,k,l;a[0][0]=0;a[0][1]=1;cin>>k;for(i=1;i<=k;i++){l=a[i-1][0];if(l-i>0&&a[l-i][1]!=1){ a[i][0]=l-i;a[l-i][1]=1;}else{ a[i][0]=l+i;a[l+i][1]=1;}cout<<a[i][0]<<endl;

Bienvenue dans la programmation des puzzles et du code Golf Stack Exchange! Veuillez modifier le nombre de caractères / octets de votre solution dans votre en-tête, comme indiqué dans les autres réponses ici. Aussi, veuillez jouer au golf votre code (par exemple, supprimer les espaces blancs pour réduire le nombre de caractères) autant que possible. Merci!
Poignée de porte

Bien sûr, je vais le faire.
Abhay Jain

1

Mathematica - 81 octets

Fold[#~Append~(#[[-1]]+If[#[[-1]]>#2&&FreeQ[#,#[[-1]]-#2],-#2,#2])&,{0},Range@#]&

Usage

Fold[#~Append~(#[[-1]]+If[#[[-1]]>#2&&FreeQ[#,#[[-1]]-#2],-#2,#2])&,{0},Range@#]&[30]
{0,1,3,6,2,7,13,20,12,21,11,22,10,23,9,24,8,25,43,62,42,63,41,18,42,17,43,16,44,15,45}

1

PHP , 89 octets

$f=function($n){for(;$i<$n;$s[$r[$i++]=$p=$m]=1)if($s[$m=$p-$i]|0>$m)$m=$p+$i;return$r;};

Essayez-le en ligne!

Non golfé:

$f = function ($n) {
    for (; $i < $n; $s[$r[$i++] = $p = $m] = 1) {
        if ($s[$m = $p - $i] | 0 > $m) {
            $m = $p + $i;
        }
    }

    return $r;
};
  • $r pour mon résultat
  • $s pour suivre les seens
  • $p valeur précédente
  • $m valeur m ext

1

LISP commun (139 octets)

(defun r(n)(do*(s(i 0(1+ i))(a 0(car s))(b 0(- a i)))((> i n)(nreverse s))(push(cond((= 0 i)0)((and(> b 0)(not(find b s)))b)(t(+ a i)))s)))

Non golfé:

(defun recaman (n)
  (do*
   (series               ; starts as empty list
    (i 0 (1+ i))         ; index variable
    (last 0 (car s))     ; last number in the series
    (low 0 (- last i)))

   ((> i n)              ; exit condition
    (nreverse series))   ; return value

    (push                ; loop body
     (cond
       ((= 0 i) 0)       ; first pass
       ((and
         (> low 0) (not (find low s)))
        low)
       (t (+ last i)))
     series)))
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.