N-й член последовательности Ван Экка


41

Выведите N-й член последовательности Ван Эка.

Последовательность Ван Экка определяется как:

  • Начинается с 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

РЕДАКТИРОВАТЬ

1 индексированный является предпочтительным, 0 индексированный является приемлемым; это может изменить некоторые из уже представленных решений.

Просто N-й срок, пожалуйста.

То же самое (за исключением того, что он видел уже опубликованную часть), кажется, что игроки в кодовый код и наблюдатели с номерами имеют приличное совпадение.


9
Смотрел видео с numpherphile на работе и собирался опубликовать это, когда я вернулся домой. Проклинаю тебя за то, что ты пришел первым. : P
Draco18s

17
Должен ли он быть 1-индексирован, или мы можем использовать 0-индексирование?
Робин Райдер

6
Можем ли мы вернуть или вывести бесконечную последовательность вместо этого?
Джо Кинг

2
... или первые nсроки?
мохнатый

@ Draco18s То же самое, я пришел сюда, чтобы опубликовать его после просмотра видео с Numberphile, когда увидел это.
Геза Кереценый

Ответы:


25

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

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

Попробуйте онлайн!

Как?

Нам не нужно хранить полную последовательность. Нам нужно только отслеживать последнюю позицию каждого целого числа, которое появляется в последовательности. Для этой цели мы используем базовый объект рекурсивной функции g .

Для данного члена p нам не нужно также устанавливать g[p] в его фактическую абсолютную позицию в последовательности, потому что нас интересует только расстояние с текущей позицией. Вот почему мы можем просто сохранить текущее значение входного n , который используется в качестве уменьшающего счетчика в коде.

Следовательно, расстояние определяется как g[p]n . Удобно, что это оценивает NaN, если это первое вхождение p , которое может быть легко превращено в ожидаемый 0 .

комментарии

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

Попробуйте онлайн!

Примечание: как отметил Эрик Outgolfer, этот код прекрасно работает и в 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для рекурсивного вызова?
АрБо

1
Я протестировал его в Python 2, и он работает.
Эрик Outgolfer

@EriktheOutgolfer хмм, а разве второе использование не распаковывает? Функция не должна поддерживать varargs для использования такого синтаксиса.
АрБо

@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

Попробуйте онлайн!

Реальная работа выполняется в глаголе итерации степенного глагола ^:, который повторяет столько раз, сколько аргумент [, начиная итерацию с константного значения 0 &0...

  • (#|1+}.i.{.)Это то, что повторяется. Разбивая это ...
  • }.i.{. Найти индекс i. заголовка списка {.в хвосте списка }.. Это вернет индекс, основанный на 0, поэтому, если текущий элемент найден равным 1, он вернет 0. Если он не найден, он вернет длину списка, то есть длину хвоста.
  • 1+Добавьте единицу к значению, чтобы исправить индексирование на основе 0, так как «насколько далеко назад» Вен Эка основано на 1. Обратите внимание, что если он не был найден, значением будет длина полного списка.
  • #|Возвращает остаток от значения, рассчитанного на предыдущем шаге, при делении на длину полного списка. Обратите внимание, что это превращает «not found» в 0, но оставляет все остальные значения без изменений.
  • ,~Добавьте новое значение в начало списка. Мы используем фронт, а не последний только для удобства.
  • 1{ вернуть 2-й элемент в списке, так как мы вычислили один слишком много раз, потому что таким образом он короче.

6

Python , 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, Richard Park и H.PWiz за помощь в написании и игре в гольф этого ответа в The APL Orchard , отличном месте для изучения APL и получения помощи APL.

Изменить: -2 байта от Адама.

⊃(⊢,⍨≢|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 Lol, мне понадобилось несколько минут, чтобы понять, что ты имел в виду, но я думаю, ты имеешь в виду F¯Rćk? ;)
Кевин Круйссен

4

Ява, 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Ḣ$;µ¡Ḣ

Монадическая ссылка, принимающая положительное целое число, N, что дает NTчас термин последовательности Ван Экка.

Попробуйте онлайн!

Как?

Ẏ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

Python 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 Но если у меня есть список в качестве аргумента по умолчанию, он не будет работать правильно для последовательных вызовов?
Руохола

Почему бы и нет?
Джонатан Фрех

1
Скорее всего, потому что ваш предыдущий скрипт изменил список, т.е. не был побочным эффектом: пример .
Джонатан Фрех




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

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