Ennesimo mandato di Van Eck Sequence


41

Stampa l'ennesimo termine della sequenza di Van Eck.

La sequenza di Van Eck è definita come:

  • Inizia con 0.
  • Se l'ultimo termine è la prima occorrenza di quel termine, il termine successivo è 0.
  • Se l'ultimo termine si è verificato in precedenza, il termine successivo è il numero di passaggi precedenti a quello più recente.

https://oeis.org/A181391

https://www.youtube.com/watch?v=etMJxB-igrc

https://www.youtube.com/watch?v=8VrnqRU7BVU

Sequenza: 0,0,1,0,2,0,2,2,1,6,0,5,0,2, ...

test:

Input | Produzione

  • 1 | 0
  • 8 | 2
  • 19 | 5
  • 27 | 9
  • 52 | 42
  • 64 | 0

MODIFICARE

1 indicizzato è preferito, 0 indicizzato è accettabile; ciò potrebbe cambiare alcune delle soluzioni già inviate.

Solo l'ennesimo termine, per favore.

Lo stesso (tranne per il fatto che la parte è già stata pubblicata), sembra che i golfisti di codice e gli osservatori dei numeri abbiano una discreta sovrapposizione.


9
Ho guardato il video numerico al lavoro e stavo per pubblicare questo quando sono tornato a casa. Ti maledico per esserci arrivato prima. : P
Draco18s

17
Deve essere 1-indicizzato o possiamo usare 0-indicizzazione?
Robin Ryder,

6
Possiamo invece restituire o emettere la sequenza infinita?
Jo King,

2
... o i primi ntermini?
Shaggy,

@ Draco18s Lo stesso, sono venuto qui per pubblicarlo dopo aver visto il video di Numberphile, quando l'ho visto.
Geza Kerecsenyi,

Risposte:


25

JavaScript (ES6),  46 41  37 byte

n=>(g=p=>--n?g(g[p]-n|0,g[p]=n):p)(0)

Provalo online!

Come?

Non è necessario memorizzare l'intera sequenza. Dobbiamo solo tenere traccia dell'ultima posizione di ciascun numero intero che appare nella sequenza. A tale scopo utilizziamo l'oggetto sottostante della funzione ricorsiva g .

Per un dato termine p , non è nemmeno necessario impostare g[p] nella sua posizione assoluta effettiva nella sequenza perché siamo interessati solo alla distanza con la posizione corrente. Ecco perché possiamo semplicemente memorizzare il valore corrente dell'input n , che viene utilizzato come contatore decrescente nel codice.

Pertanto, la distanza è data da g[p]n . Convenientemente, questo restituisce a NaN se questa è la prima occorrenza di p , che può essere facilmente trasformata nello 0 previsto0 .

Commentate

n => (             // n = input
  g = p =>         // g = recursive function taking p = previous term of the sequence
                   //     g is also used as an object to store the last position of
                   //     each integer found in the sequence
    --n ?          // decrement n; if it's not equal to 0:
      g(           //   do a recursive call:
        g[p] - n   //     subtract n from the last position of p
                   //     if g[p] is undefined, the above expression evaluates to NaN
        | 0,       //     in which case we coerce it to 0 instead
        g[p] = n   //     update g[p] to n
      )            //   end of recursive call
    :              // else:
      p            //   we've reached the requested term: stop recursion and return it
)(0)               // initial call to g with p = 0

18

Python 3 , 69 63 62 byte

f=lambda n,l=0,*s:f(n-1,l in s and~s.index(l),l,*s)if n else-l

Provalo online!

Nota: come menzionato da Erik the Outgolfer, questo codice funziona bene anche in Python 2.

0-indicizzato (anche se, solo per essere assolutamente perverso, puoi renderlo -1-indicizzato cambiando if nin if~n: P)

Utilizza lo splendido "operatore a stella" di Python per il disimballaggio, per costruire ricorsivamente la serie, fino a nraggiungere lo zero.

La funzione costruisce le serie nell'ordine inverso, per evitare di doverle invertire per la ricerca. Inoltre, in realtà memorizza le negazioni di tutti gli elementi, perché riconvertirli alla fine era libero (altrimenti -avrebbe dovuto essere uno spazio) e ci salva un byte lungo la strada, usando ~s.index(l)invece di-~s.index(l) .

Potrebbero essere 51 byte se le tuple Python avessero le stesse findfunzioni delle stringhe (restituendo -1 se non trovato, invece di generare un errore), ma nessuna tale fortuna ...


3
In realtà, l '"operatore a stella" che stai usando non è l'operatore di decompressione di Python 3, ma piuttosto l'operatore vararg che esiste anche in Python 2.
Erik the Outgolfer

3
Il primo è, ma il secondo non è il disimballaggio sper la chiamata ricorsiva?
ArBo,

1
L'ho provato in Python 2 e funziona.
Erik the Outgolfer,

@EriktheOutgolfer hmm, ma il secondo utilizzo non è il disimballaggio? La funzione non deve supportare varargs per utilizzare tale sintassi.
ArBo,

@ArBo: non è diverso da def func(f, *args): f(*args); il disimballaggio all'interno delle chiamate di funzione è valido py2. Cosa c'è di PY3 per soli disimballaggio all'interno comprensioni lista / dict (ad esempio [1, 2, *s]) o disimballaggio variabili: a, *b = [1,2,3,4].
Ehsan Kia,

9

R , 62 byte

function(n){while(sum(F|1)<n)F=c(match(F[1],F[-1],0),F)
+F[1]}

Provalo online!

Costruisce l'elenco al contrario; matchrestituisce il primo indice di F[1](il valore precedente) in F[-1](il resto dell'elenco), restituendo0 se non viene trovata alcuna corrispondenza.

Fviene inizializzato FALSEe costretto al 0primo passaggio del whileloop.


2
Sono un po 'sbalordito da quanto matchè buono per questo problema quando lo costruisci in questo modo. Veramente pulito.
CriminallyVulgar

Il plus sulla seconda riga fa qualcosa qui? Ho pensato che risolvesse un caso limite, ma non riesco a trovarne uno.
CriminalmenteVolgar

1
@CriminallyVulgar dovrebbe costringere Fa 0quando n==1altrimenti sarebbe tornato FALSE.
Giuseppe,

Ah! Capisco. Ha senso, stavo provando molte gamme ma non il singolo valore.
CriminallyVulgar

9

Perl 6 , 47 42 byte

-5 byte grazie a nwellnhof

{({+grep(@_[*-1],:k,[R,] @_)[1]}...*)[$_]}

Provalo online!

Blocco codice anonimo che genera l'elemento con indice 0 nella sequenza.

Spiegazione:

{                                            } # Anonymous codeblock
 (                                      )[$_]  # Return the nth element
                                    ...*       # Of the infinite sequence
  {                            }  # Where each element is
    grep(        :k        )[1]   # The key of the second occurrence
         @_[*-1],                 # Of the most recent element
                   ,[R,] @_       # In the reversed sequence so far
   +     # And numify the Nil to 0 if the element is not found

8

Bourne shell, 102 bytes

until [ 0"$i" -eq $1 ];do i=$((${i:-0}+1)) a=${n:-0};eval 'n=$(($i-${m'$a:-$i'}))' m$a=$i;done;echo $a

try it online


3
Welcome to PPCG!
Arnauld


6

J, 29 23 bytes

1{(,~#|1+}.i.{.)@]^:[&0

Try it online!

The real work is done in the iteration verb of the power verb ^:, which iterates as many times as the argument [, starting the iteration with the constant value 0 &0...

  • (#|1+}.i.{.) This is what iterates. Breaking it down...
  • }.i.{. Find the index of i. of the head of the list {. within the tail of the list }.. This will return a 0-based index, so if the current item is found 1 previous it will return 0. If it is not found, it will return the length of the list, ie, the length of the tail.
  • 1+ Add one to the value to correct for the 0-based indexing, since the Ven Eck's "how far back" is 1-based. Note that if it was not found, the value will now be the length of the full list.
  • #| Return the remainder of the value calculated in the previous step, when divided by the length of the full list. Note that this turns "not found" into 0, but leaves all other values unchanged.
  • ,~ Append the new value to the front of the list. We use the front rather than last merely for convenience.
  • 1{ return the 2nd item in the list, since we calculated one too many times because it's shorter that way.

6

Python, 51 bytes

f=lambda n,i=1:n>i and[f(n,i+1),i][f(n-1)==f(n+~i)]

Try it online!

Outputs False for 0. Implements the spec pretty literally, looking for the lowest positive integer i such that f(n-1)==f(n-i-1). If such a search leads to i>=n, the previous element hasn't appeared before and we produce 0.

Instead of doing something reasonable like storing earlier values in a list, the function just recomputes them recursively from scratch whenever they're needed, and sometimes when they're not needed. This makes the function run very slowly for inputs above 10 or so.


5

APL (Dyalog Unicode), 19 17 bytesSBCS

Many thanks to ngn, Adám, Richard Park and H.PWiz for their help in writing and golfing this answer in The APL Orchard, a great place to learn APL and get APL help.

Edit: -2 bytes from Adám.

⊃(⊢,⍨≢|1∘↓⍳⊃)⍣⎕-1

Try it online!

Explanation

⊃(⊢,⍨≢|1∘↓⍳⊃)⍣⎕-1

                 -1  We initialize our array of results with -1.
 (           )⍣⎕     repeats the train (in parentheses) our input, ⎕, times.
        1∘↓⍳⊃        We take the index of the head (our last element in the sequence).
                     To signify "element not found", this returns the length of the array.
      ≢|             We take our index modulo the length of the array.
                     This turns our "element not found" from the length of the array to 0.
  ⊢,⍨                And we prepend to our array.
                    Finally, we return the first element of the array,
                     which is the most recently-generated.
                     This is the ⍵-th element of the Van Eck sequence.


4

05AB1E, 8 bytes

F¯Rćk>Dˆ

Try it online or output the first n values in the list.

Explanation:

F         # Loop the (implicit) input amount of times:
 ¯        #  Push the global array
  R       #  Reverse it
   ć      #  Extract the head; push the remainder and the head to the stack
    k     #  Get the 0-based index of the head in the remainder (-1 if not found)
     >    #  Increase it by 1 to make it 1-indexed (or 0 if not found)
      Dˆ  #  Add a copy to the global array
          # (after the loop, output the top of the stack implicitly as result,
          #  which is why we need the `D`/duplicate)

1
That's a weird way to censor profanity!
negative seven

1
@negativeseven Lol, took me a few minutes to know what you meant, but I guess you're referring to the F¯Rćk? ;)
Kevin Cruijssen

4

Java, 96 80 76 bytes

n->{int i,v=0,m[]=new int[n];for(;--n>0;m[v]=n,v=i<1?0:i-n)i=m[v];return v;}

Not obfuscated:

Function<Integer, Integer> vanEck =
n -> {

    int i;                  // i is the value of n when v was previously encountered
    int v = 0;              // v is the current element of vanEck sequence
    int[] m = new int[n];   // m[v] is the value of n when v was previously encountered

    while (--n > 0) {       // n is used as a decrementing counter

        i = m[v];
        m[v] = n;
        v = i == 0 ? 0 : i - n;
    }

    return v;
};

2
You should be able to remove a few bytes by changing the while loop to a for loop.
MegaTom

1
Hello, you could golf more by inlining the declaration of int[] in the int declaration, and also use <1 instead of ==0. Example: int f(int n){int l[]=new int[n],i=0,j,v=0;while(++i<n){j=l[v];l[v]=i;v=j<1?0:i-j;}return v;}
Olivier Grégoire

2
And now a lambda, as well as the golf mentioned by @MegaTom for a total of 80 bytes: n->{int l[]=new int[n],i=0,j,v=0;for(;++i<n;l[v]=i,v=j<1?0:i-j)j=l[v];return v;}
Olivier Grégoire

1
Finally, you can check for tips for golfing in Java.
Olivier Grégoire

3

Charcoal, 23 bytes

≔⁰θF⊖N«≔⊕⌕⮌υθη⊞υθ≔ηθ»Iθ

Try it online! Link is to verbose version of code. Explanation:

≔⁰θ

Set the first term to 0.

F⊖N«

Loop n-1 times. (If 0-indexing is acceptable, the can be removed for a 1-byte saving.)

≔⊕⌕⮌υθη

The next term is the incremented index of the current term in the reversed list of previous terms.

⊞υθ

Add the current term to the list of previous terms.

≔ηθ

Set the current term to the next term.

»Iθ

Print the current term at the end of the loop.



2

Jelly, 8 bytes

ẎiḢ$;µ¡Ḣ

A monadic Link accepting a positive integer, n, which yields the nth term of the Van Eck Sequence.

Try it online!

How?

ẎiḢ$;µ¡Ḣ - Link: n
     µ¡  - repeat this monadic link n times - i.e. f(f(...f(n)...)):
         - (call the current argument L)
Ẏ        -   tighten (ensures we have a copy of L, so that Ḣ doesn't alter it)
   $     -   last two links as a monad:
  Ḣ      -     head (pop off & yield leftmost of the copy)
 i       -     first index (of that in the rest) or 0 if not found
    ;    -   concatenate with L
       Ḣ - head

Note that without the final we've actually collected [a(n), a(n-1), ..., a(2), a(1), n]



2

Haskell, 68 67 66 bytes

Quite straightforward implementation (using 0 based indexing).

f n|all((/=f(n-1)).f)[0..n-2]=0|m<-n-1=[k|k<-[1..],f(m-k)==f m]!!0

Try it online!


2

Haskell, 61 bytes

(([]#0)1!!)
(l#n)i=n:(((n,i):l)#maybe 0(i-)(lookup n l))(i+1)

0-based indexing.

Try it online!




2

Python 3, 128 114 111 102 99 bytes

102 -> 99 bytes, thanks to Jonathan Frech

f=lambda n,i=1,l=[0]:f(n,i+1,l+[l[i-2::-1].index(l[-1])+1if l[-1]in l[:-1]else 0])if n>i else l[-1]

Try it online!


You can negate your condition and use - instead of != to save a byte.
Jonathan Frech

Also, since your golf appears to be side-effect-less, you can use lists instead of tuples.
Jonathan Frech

@JonathanFrech But if I have a list as default argument it will not work correctly for consecutive calls?
ruohola

Why should it not?
Jonathan Frech

1
Most likely because your previous script modified the list, i.e. was not side-effect-less: example.
Jonathan Frech


1

Python 3, 112 bytes

a=[0]
for _ in a*int(input()):k=a[-1];a+=k in a[:-1]and[a[::-1].index(k)+~a[-2::-1].index(k)]or[0]
print(-a[-2])

Try it online!

-3 bytes thanks to mypetlion


Second line can become for _ in a*int(input()):k=a[-1];a+=k in a[:-1]and[a[::-1].index(k)+~a[-2::-1].index(k)]or[0] to save 3 bytes.
mypetlion

@mypetlion thanks
HyperNeutrino


1

CJam (15 bytes)

0a{_(#)\+}qi*0=

Online demo. This is a full program and 0-indexed.

Dissection

0a      e# Push the array [0]
{       e# Loop...
  _(#   e#   Copy the array, pop the first element, and find its index in the array
  )\+   e#   Increment and prepend
}qi*    e# ... n times, where n is read from stdin
0=      e# Take the first element of the array

0

Clojure, 69 bytes

#((fn f[i c t](if(= i 1)t(f(dec i)(assoc c t i)(-(or(c t)i)i))))%{}0)

Sadly a more functional approach seems to be longer.


0

DC, 94 91 90 bytes

Input is taken during the program. Save this to a file and then do "dc " to run. Definitely not the shortest, but I have fun with challenges like these in dc. Input is 1-based index, as preferred.

[st1si0swlbxltlwlu1-sulu0!=m]sm[dlt=qSsli1+siz0!=b0siLs]sb[0pq]sf[lisw2Q]sq?2-dsu1>f0dlmxp

Main control macro
[st                         ]sm   save top value as target
[  1si0sw                   ]sm   reset i to 1 and w to 0
[        lbx                ]sm   execute macro b to get next value in w
[           ltlw            ]sm   restore target to the stack and add w to the stack
[               lu1-su      ]sm   decrement the user inputted variable
[                     lu0!=m]sm   if the user inputted variable is not 0 recurse

Next value finder macro
[dlt=q                  ]sb     if the value on the stack is the target, quit
[     Ss                ]sb     save top value to s register
[       li1+si          ]sb     increment i register
[             z0!=b     ]sb     recurse if still more values            
[                  0si  ]sb     set i to 0 (will be saved to w if relevant)
[                     Ls]sb     move top value of s register to stack

[lisw2Q]sq   Load i, save it to w, and then quit this macro and the one that called it

[0pq]sf print 0 and quit the program
```

0

C++ (clang), 241 235 234 219 197 189 bytes

197 -> 189 bytes, thanks to ceilingcat

#import<bits/stdc++.h>
int f(int n,int i=0,std::vector<int>l={0}){return~-n>i?l.push_back(find(begin(l),end(l)-1,l[i])-end(l)+1?find(rbegin(l)+1,rend(l),l[i])-rbegin(l):0),f(n,i+1,l):l[i];}

Try it online!


0

Pyth, 18 bytes

VQ=Y+?YhxtYhY0Y;hY

Try it online!

Builds up the sequence in reverse and prints the first element (last term of the sequence).

VQ                 # for N in range(Q) (Q=input)
  =Y+         Y    # Y.prepend(
        xtY        #   Y[1:].index(    )
           hY      #               Y[0]
       h           #                     +1
     ?Y      0     #                        if Y else 0)
               ;hY # end for loop and print Y[0]
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.