N-й термін Послідовності Ван Ека


41

Виведіть n-й термін послідовності Ван-Ека.

Послідовність Van Eck визначається як:

  • Починається з 0.
  • Якщо останній член є першим виникненням цього терміна, наступний додаток дорівнює 0.
  • Якщо останній термін відбувся раніше, наступний термін - це скільки кроків назад було останнім явищем.

https://oeis.org/A181391

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

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

Послідовність: 0,0,1,0,2,0,2,2,1,6,0,5,0,2, ...

Тести:

Введення | Вихідні дані

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

EDIT

1 індексований варіант кращий, 0 індексований є прийнятним; що може змінити деякі вже подані рішення.

Просто N-й термін, будь ласка.

Це ж (за винятком того, що він вже розмістив його частину), схоже, що гольфісти і чисельні спостерігачі мають пристойне перекриття.


9
Дивився відео нумерофілів на роботі і збирався опублікувати це, коли я повернувся додому. Проклинаю тебе за те, що першим потрапив туди. : P
Draco18s

17
Чи має бути 1-індексований чи ми можемо використовувати 0-індексацію?
Робін Райдер

6
Чи можемо ми замість цього повернути чи вивести нескінченну послідовність?
Джо Кінг

2
... або перші nтерміни?
Кудлатий

@ Draco18s Те саме, я прийшов сюди, щоб опублікувати його після перегляду відео Numberphile, коли побачив це.
Geza Kerecsenyi

Відповіді:


25

JavaScript (ES6),  46 41  37 байт

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

Спробуйте в Інтернеті!

Як?

Нам не потрібно зберігати повну послідовність. Нам потрібно лише відслідковувати останню позицію кожного цілого числа, що з’являється в послідовності. Для цього ми використовуємо основний об'єкт рекурсивної функції .g

Для даного терміна нам не потрібно встановлювати на його фактичне абсолютне положення у послідовності, оскільки нас цікавить лише відстань до поточної позиції. Ось чому ми можемо просто зберегти поточне значення вхідного , яке використовується як лічильник зменшення в коді.pg[p]n

Тому відстань задається . Зручно, це оцінюється для NaN, якщо це перше виникнення , яке можна легко перетворити на очікуване .g[p]np 0p0

Прокоментував

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 байт

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

Спробуйте в Інтернеті!

Примітка: як згадував Ерік Атголфер, цей код чудово працює і в Python 2.

0-індексований (хоча, щоб бути абсолютно збоченим, ви можете зробити його -1-індексованим, змінивши if nна if~n: P)

Використовує чудове розпакування "зіркового оператора" Python для рекурсивного збирання серії, поки не nдосягне нуля.

Функція будує серію в зворотному порядку, щоб уникнути необхідності її повернення для пошуку. Крім того, він фактично зберігає заперечення всіх елементів, тому що перетворення їх назад в кінці було безкоштовним (інакше -мав би бути пробіл) і це економить нам байт по дорозі, використовуючи ~s.index(l)замість цього -~s.index(l).

Може бути 51 байт, якби кортежі Python мали ті ж findфункції, що і рядки (повернення -1, якщо його не знайдено, замість того, щоб викликати помилку), але такої удачі немає ...


3
Насправді "зірковий оператор", який ви використовуєте, не є оператором розпакування Python 3, а скоріше оператором vararg, який також існує в Python 2.
Ерік Outgolfer

3
Перший є, але чи не другий розпаковується sдля рекурсивного дзвінка?
ArBo

1
Я тестував його в Python 2, і він працює.
Ерік Аутгольфер

@EriktheOutgolfer Хм, але хіба це не друге використання для розпакування? Функція не повинна підтримувати varargs, щоб використовувати такий синтаксис.
ArBo

@ArBo: Це не відрізняється від def func(f, *args): f(*args); розпакування внутрішніх викликів функцій є дійсним py2. Що PY3-тільки розпакування всередині списку / Dict осягань (тобто [1, 2, *s]) або розпакування змінні: a, *b = [1,2,3,4].
Ехсан Кіа

9

R , 62 байти

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

Спробуйте в Інтернеті!

Створює список у зворотному порядку; matchповертає перший індекс F[1](попереднє значення) у F[-1](залишок списку), повертаючи, 0якщо не знайдено відповідності.

Fініціалізується до FALSEта примушується до 0першого проходу whileциклу.


2
Мені якось в захваті від того, наскільки добре matchдля цієї проблеми, коли ви будуєте її таким чином. Дійсно чистий.
Кримінально-

Чи робить плюс у другому рядку щось тут? Я припустив, що це виправлений край, але я не можу його знайти.
Кримінально-

1
@CriminallyVulgar він повинен примушувати Fдо 0коли n==1ж він повернеться FALSE.
Джузеппе

А-а, я бачу. Має сенс, я намагався багато діапазонів, але не єдине значення.
Кримінально-

9

Perl 6 , 47 42 байт

-5 байт завдяки nwellnhof

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

Спробуйте в Інтернеті!

Анонімний кодовий блок, який виводить 0-індексований елемент у послідовності.

Пояснення:

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



6

J , 29 23 байти

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

Спробуйте в Інтернеті!

Справжня робота робиться в ітераційному дієслові дієслова power ^:, який повторюється стільки разів, скільки аргумент [, починаючи ітерацію з постійного значення 0 &0...

  • (#|1+}.i.{.)Це те, що повторює. Розбивши його ...
  • }.i.{.Знайдіть індекс i.голови списку {.в межах хвоста списку }.. Це поверне індекс на основі 0, тому якщо поточний елемент знайдений 1 попередній, він поверне 0. Якщо його не буде знайдено, він поверне довжину списку, тобто довжину хвоста.
  • 1+Додайте його до значення, щоб виправити індексацію на основі 0, оскільки значення "наскільки назад" Ven Eck засноване на 1. Зауважте, що якщо його не було знайдено, значенням тепер буде довжина повного списку.
  • #|Поверніть решту значення, обчислене на попередньому кроці, поділене на довжину повного списку. Зауважте, що це перетворюється "не знайдено" в 0, але всі інші значення залишаються незмінними.
  • ,~Додайте нове значення на передню частину списку. Ми використовуємо фронт, а не останній лише для зручності.
  • 1{ повернути 2-й елемент у списку, оскільки ми обчислили його занадто багато разів, тому що це коротше.

6

Пітон , 51 байт

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

Спробуйте в Інтернеті!

Виходи Falseдля 0. Реалізує специфікацію досить буквально, шукаючи найнижнє додатне ціле число iтаке f(n-1)==f(n-i-1). Якщо такий пошук призводить до i>=n, попередній елемент раніше не з’являвся, і ми виробляємо 0.

Замість того, щоб робити щось розумне, як зберігання попередніх значень у списку, функція просто перераховує їх рекурсивно з нуля, коли вони знадобляться, а іноді, коли вони не потрібні. Це змушує функцію працювати дуже повільно для входів вище 10 або близько того.


5

APL (Dyalog Unicode) , 19 17 байт SBCS

Велике спасибі ngn, Adám, Річард Парк та H.PWiz за допомогу в написанні та гольфі на цю відповідь у Фруктовому саду APL - прекрасне місце для вивчення APL та отримання довідки APL.

Редагувати: -2 байти від Adám.

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

Спробуйте в Інтернеті!

Пояснення

⊃(⊢,⍨≢|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 байт

F¯Rćk>Dˆ

n

Пояснення:

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
Це дивний спосіб нецензурної лексики!
мінус сім

1
@negativeseven Лол, мені знадобилося кілька хвилин, щоб знати, що ти маєш на увазі, але я думаю, ти маєш на увазі F¯Rćk? ;)
Кевін Круїссен

4

Java, 96 80 76 байт

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

Не затуманено:

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
Ви повинні мати змогу видалити кілька байт, змінивши цикл while на цикл for.
MegaTom

1
Привіт, ви могли гольф більше, вбудовування декларації int[]в intдекларації, а також використовувати <1замість ==0. Приклад: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;}
Олів'є Грегоар

2
А тепер лямбда, а також гольф, згаданий @MegaTom, на загальну суму 80 байт: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;}
Олів'є Грегоар,

1
Нарешті, ви можете перевірити поради щодо гольфу на Java .
Олів'є Грегоар

3

Вугілля деревне , 23 байти

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

≔⁰θ

Встановіть перший додаток на 0.

F⊖N«

n-1Часи циклу . (Якщо 0-індексація прийнятна, її можна видалити для 1-байтового збереження.)

≔⊕⌕⮌υθη

Наступний доданок - це індексований індекс поточного терміна в переверненому списку попередніх термінів.

⊞υθ

Додайте поточний термін до списку попередніх термінів.

≔ηθ

Встановіть поточний термін на наступний термін.

»Iθ

Надрукуйте поточний термін у кінці циклу.



2

Желе , 8 байт

ẎiḢ$;µ¡Ḣ

nnth

Спробуйте в Інтернеті!

Як?

Ẏ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

Зауважте, що без фіналу ми насправді зібрали[a(n), a(n-1), ..., a(2), a(1), n]







2

Пітон 3 , 128 114 111 102 99 байт

102 -> 99 байт, завдяки Джонатану Фреху

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]

Спробуйте в Інтернеті!


Ви можете заперечувати свій стан і використовувати -замість цього, !=щоб зберегти байт.
Джонатан Фрех

Крім того, оскільки ваш гольф видається побічним ефектом, ви можете використовувати списки замість кортежів.
Джонатан Фрех

@JonathanFrech Але якщо у мене аргумент списку як аргумент за замовчуванням, він не працюватиме правильно для послідовних дзвінків?
ruohola

Чому це не слід?
Джонатан Фрех

1
Швидше за все, тому що ваш попередній скрипт змінив список, тобто не був побічним ефектом: example .
Джонатан Фрех




1

CJam (15 байт)

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

Інтернет демо . Це повна програма і 0-індексована.

Розсічення

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 байт

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

На жаль, здається, функціональніший підхід довший.


0

DC, 94 91 90 байт

Введення проводиться під час програми. Збережіть це у файлі, а потім виконайте "dc" для запуску. Безумовно, не найкоротший, але мені цікаво з такими проблемами, як у DC. Введення - 1-базовий індекс, як бажано.

[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

Піт , 18 байт

VQ=Y+?YhxtYhY0Y;hY

Спробуйте в Інтернеті!

Створює послідовність у зворотному порядку і друкує перший елемент (останній член послідовності).

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.