Genera la sequenza di Recamán


20

La sequenza di Recamán ( A005132 ) è una sequenza matematica, definita come tale:

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

Una versione piuttosto LaTex di cui sopra (potrebbe essere più leggibile):

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

I primi termini sono 0, 1, 3, 6, 2, 7, 13, 20, 12, 21, 11

Per chiarire, is newsignifica se il numero è già nella sequenza.

Dato un numero intero n, tramite argomento di funzione o STDIN, restituisce i primi ntermini della sequenza di Recamán.


Questa è una sfida di code-golf, quindi vince il codice più corto.


Cosa significa "nuovo"?
Decadimento beta

Se un numero è nuovo, significa che non è ancora nella sequenza. Ho appena realizzato che ho sbagliato a scrivere la sequenza, dammi un minuto per correggerla.
James Williams,

Corretta la sequenza.
James Williams,

1
Puoi aggiungere i primi valori della sequenza?
orgoglioso haskeller,

Aggiunti i primi numeri! (E un link alla sua pagina OEIS)
James Williams,

Risposte:


9

CJam, 34 33 byte

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

Provalo online.

Esempio di esecuzione

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

Come funziona

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:]).                                     ";

Che cambiamento hai fatto?
Soham Chowdhury,

Il mio primo approccio ha anteposto numeri negativi alla sequenza, quindi non ho dovuto verificare esplicitamente se A(i) - i > 0. Tuttavia, non ho anteposto abbastanza numeri per piccoli valori di n. Ora, faccio esattamente quello che dice la specifica.
Dennis,

33 contro 45. Così vicini eppure così lontani. :)
Ingo Bürk,

Caspita, commento senza e#in Cjam ... gustosa ciliegia.
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)

Esempio di utilizzo:

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

6

Rubino, 71 70 byte

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

Un'implementazione molto "parola per parola" della definizione.


5

Python 2, 78 75 73 69 byte

Complimenti per xnor e flornquake
Ora quasi 10 byte in meno rispetto alla risposta iniziale

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

È possibile ridurre [k,k+2*p][bool]a k+2*p*(bool).
xnor,

@xnor Grazie, salvato 3 byte.
Markuz,

Inoltre, k in m or k<0può essere k*(k>=0)in mpoiché if k<0, il prodotto è 0, che è in m.
xnor,

@xnor Brilliant! Grazie ancora
Markuz,

Puoi scrivere -1invece di p-1. Modifica: puoi anche creare muna tupla e scrivere m=0,e m+=k+2*p*(k*(k>0)in m),.
terremoto del

4

Golfscript (41 45 )

Provalo online qui :

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

Spiegazione

Questo è per la soluzione originale a 45 byte, ma è ancora praticamente la stessa:

(,              # 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

Modifica n. 1: grazie a Dennis per la rasatura di 4 byte.


4

dc , 46 byte

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

Provalo online!

Questo programma prende input da uno stack altrimenti vuoto e output a stdout (delimitato da nuova riga).

Sono davvero orgoglioso di questo - sta battendo tutto ciò che non è un linguaggio dedicato al golf e mette in mostra tre dei miei trucchi di golf DC preferiti:

  • Dimensione dello stack utilizzata come variabile indice
  • Rifattorizzare "se A allora B altrimenti C" in "incondizionatamente C, e se A quindi D" dove C e D si combinano per formare B
  • la funzione dell'array ad accesso casuale poco utilizzata per risolvere un vincolo di unicità

Spiegazione

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

questo è selvaggio, non avevo idea che esistesse
don Bright

3

JavaScript - 81 80 79 70

Complimenti a edc65 per avermi aiutato a salvare 9 byte

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 => {for (a = [x = i = 0]; ++ i <n;) a [i] = x + = x> i & a.indexOf (xi) <0? -I: i ; return a}
edc65

@ edc65 Grazie mille :)
William Barbosa,

3

JavaScript, ES6, 74 69 caratteri

Esegui il codice seguente nell'ultima console Web di Firefox.

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

Proverò a giocare a golf più tardi.

Esempio di utilizzo:

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

3

MATLAB, 83 78 byte

Salvare il valore seguente come f.m(73 byte)

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

Esegui dalla finestra di comando (5 byte)

n=9;f

Se quanto sopra non è legale, richiede 90 byte.

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 caratteri

golfed:

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

Ungolfed:

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

Esempio di esecuzione:

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

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

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

-5 byte grazie a Jo King

Provalo online!


è fantastico ... sembra letteralmente che il mio gatto abbia attraversato la mia tastiera.
don luminoso

3

05AB1E , 19 byte

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

Provalo online!

Spiegazione

¾ˆ                    # 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

Come funziona?
Lirtosiast

@lirtosiast: è passato un po 'di tempo da quando ho fatto questa sfida, quindi questa è la migliore spiegazione che posso fare in breve tempo. Spero sia abbastanza.
Emigna,

3

K (oK) , 53 byte

Soluzione:

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

Provalo online!

Spiegazione:

Soluzione ricorsiva.

{$[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

versione leggibile:

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

Uso 2 tavoli, il primo è chiamato un ed è costruito in modo tale che a [i] = 1 se e solo se i è già apparso in sequenza, nil altrimenti, mentre la seconda tabella effettivamente contiene la sequenza


La tua sequenza dovrebbe iniziare con 0, però
William Barbosa,

1
Hai ragione, non ho esaminato la domanda molto attentamente e ho ipotizzato che avesse la stessa definizione in mathworld (a partire da 1), penso che non costerà più carattere, lo testerò e lo correggerò più tardi, Sto scrivendo dal mio telefono ora!

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

Modifica 1: grazie ai suggerimenti di @ xnor sull'altra risposta di Python! (Mi sono appena reso conto che entrambi sembrano molto simili.)

Modifica 2: grazie ancora, @xnor.


Questo dà un ciclo infinito. Hai bisogno di una sorta di flusso di controllo in modo che f(x)non sempre si chiami immediatamente f(x-1).
xnor,

@xnor ha corretto il codice.
Soham Chowdhury,

1
Questo sembra restituire l'ennesimo termine, non i primi n.
Dennis,

Alcuni salvataggi minori: t=0possono andare come parametro facoltativo a fe t=t+possono esserlo t+=.
xnor,

2

Groovy: 122 118 111 caratteri

golfed:

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

Ungolfed:

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

Esempio di esecuzione:

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

2

Clojure: 174 caratteri

golfed:

(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]))

Ungolfed:

(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]) )

Esecuzione di esempio:

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
Ti suggerisco di non leggere da STDIN, ma piuttosto di prendere un argomento intero per la funzione :) Inoltre non ottieni alcun vantaggio dalla definizione ynel letmodulo, puoi usare l'espressione direttamente dove è necessario il valore.
NikoNyrh,

2

Mathcad, 54 "byte"

inserisci qui la descrizione dell'immagine


Dal punto di vista dell'utente, Mathcad è effettivamente una lavagna 2D, con espressioni valutate da sinistra a destra, dall'alto verso il basso. Mathcad non supporta un input di "testo" convenzionale, ma utilizza invece una combinazione di testo e tasti speciali / barra degli strumenti / voci di menu per inserire un'espressione, testo, trama o componente. Ad esempio, digitare ":" per inserire l'operatore di definizione (mostrato sullo schermo come ": =") o "ctl-shft- #" per inserire l'operatore for loop (inclusi i segnaposto per la variabile di iterazione, i valori di iterazione e un corpo espressione). Quello che vedi nell'immagine sopra è esattamente ciò che appare nell'interfaccia utente e come "digitato" in.

Ai fini del golf, il conteggio dei "byte" è il numero equivalente di operazioni da tastiera richieste per inserire un'espressione.


Va tutto bene , ma quali sono i tasti premuti?
Jo King,


2

Stax , 19 byte

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

Esegui ed esegui il debug

Disimballato, non golfato e commentato, sembra così. Mantiene la sequenza finora in pila e si ricorda A(n - 1)nel registro X. L'indice di iterazione viene utilizzato per n. La prima volta, è 0, ma in quella iterazione genera lo 0 senza casi particolari, quindi non è necessario regolare l'indice 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

Esegui ed esegui il debug di questo


interessante. come funziona?
don luminoso

1
@donbright: aggiunte alcune annotazioni e spiegazioni.
ricorsivo il


2

Pyth , 24 byte

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

Provalo online!

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

Un'altra implementazione 'parola per parola' anche qui. Sorprendentemente leggibile anche per PowerShell.

La sequenza è memorizzata nella matrice $ a e stampata un termine per riga.

Per $ n = 20 se eseguiamo la dichiarazione $a-join","che otteniamo

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

1

C #: 140 caratteri

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 caratteri (158 senza istruzioni cin e 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;

Benvenuti in Puzzle di programmazione e scambio di code di golf! Modifica il conteggio di caratteri / byte della soluzione nell'intestazione, come mostrato nelle altre risposte qui. Inoltre, per favore golf il tuo codice (es. Rimuovi spazi bianchi per ridurre il numero di caratteri) il più possibile. Grazie!
Maniglia della porta

Certo, lo farò.
Abhay Jain,

1

Mathematica - 81 byte

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

uso

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 byte

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

Provalo online!

Ungolfed:

$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 per il mio risultato
  • $s per il monitoraggio dei visti
  • $p valore precedente
  • $m m valore ext

1

LISP comune (139 byte)

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

Ungolfed:

(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)))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.