Коливання послідовності Голомба


21

OEIS має варіацію (A111439) у послідовності Голомба . Як і в послідовності Голомба, A(n)описується, як часто nз'являється в послідовності. Але крім того, жодні дві послідовні номери не можуть бути однаковими. Під час створення послідовності A(n)завжди вибирається як найменше додатне ціле число, яке не порушує цих двох властивостей. Через заборонені послідовні однакові номери серія коливається вгору та вниз, коли вона росте. Ось перші 100 термінів:

1, 2, 3, 2, 3, 4, 3, 4, 5, 6, 5, 6, 5, 6, 7, 6, 7, 8, 7, 8, 9, 8, 9, 8, 9, 
10, 9, 10, 9, 10, 11, 10, 11, 10, 11, 10, 11, 12, 11, 12, 13, 12, 13, 12, 
13, 12, 13, 12, 13, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 16, 15, 
16, 17, 16, 17, 16, 17, 16, 17, 16, 17, 18, 17, 18, 17, 18, 19, 18, 19, 18, 
19, 18, 19, 18, 19, 18, 19, 20, 19, 20, 21, 20, 21, 20, 21, 20, 21, 20

Повний список перших 10000 номерів можна знайти на OEIS .

Завдання полягає в написанні програми або функції, яка обчислює A(n), задану n. nє 1-О для того, щоб самоопісиваемое властивості працює.

Правила

Ви можете написати програму чи функцію та скористатися будь-яким із наших стандартних методів отримання вводу та надання виводу.

Ви можете використовувати будь-яку мову програмування , але зауважте, що ці лазівки за замовчуванням заборонені.

Це , тому найкоротший вірний відповідь - вимірюється в байтах - виграє.

Випробування

n     A(n)
1     1
4     2
10    6
26    10
100   20
1000  86
1257  100
10000 358


3
Мені було цікаво, тому я зрозумів це . Неато.
Інженер Тост

4
@EngineerToast Графік також знаходиться на OEIS. Я розглядав, як довго ви бачите на своєму графіку "пробіжки", і це стає дивно . (Цей графік показує, як часто Nз’являється після останнього виникнення, N-1яке вимірює кількість коливань до N.)
Мартін Ендер

Відповіді:


5

Haskell , 67 байт

f k|k<4=k|p<-k-1=[n|n<-[1..],n/=f p,sum[1|a<-[1..p],f a==n]<f n]!!0

Визначає функцію f. Спробуйте в Інтернеті! Це дуже повільно, обчислюючи f 15час на TIO.

Пояснення

Просто з визначенням: на кожному етапі вибирайте мінімальне додатне число, nяке задовольняє обмеженням (не рівним попередньому запису та ще не відбулося f nразів).

f k             -- Define f k:
 |k<4=k         -- If k < 4, it's k.
 |p<-k-1=       -- Otherwise, bind k-1 to p,
  [n|           -- compute the list of numbers n where
   n<-[1..],    -- n is drawn from [1,2,3,...],
   n/=f p,      -- n is not equal to f p, and
   sum[1|       -- the number of
    a<-[1..p],  -- those elements of [1,2,3,...,p]
    f a==n]     -- whose f-image equals n
   <f n]        -- is less than f n,
  !!0           -- and take the first element of that list.

5

Математика, 69 68 байт

Дякую Мартіну Ендеру, що знайшов для мене зайвий -1 байт!

Last@Nest[{##&@@#,1//.x_/;x==Last@#||#~Count~x==#[[x]]->x+1}&,{},#]&

Безіменна функція, що приймає додаткове ціле число nяк вхідне і повертає додатне ціле число. Будуємо весь список перших nелементів цієї послідовності, потім беремо Lastелемент. Список будується, починаючи з порожнього списку {}і оперуючи ним з функціями nраз підряд (через Nest).

Розглянута функція полягає в тому {##&@@#,1//.x_/;x==Last@#||#~Count~x==#[[x]]->x+1}&, що приймає частковий перелік значень послідовностей (по суті ##&@@#) і додає до неї наступне значення. Наступне значення обчислюється, починаючи з x=1, а потім повторно замінюючи xдо x+1тих пір, поки умова x==Last@#||#~Count~x==#[[x]]буде виконана - іншими словами, якщо або xє попереднім елементом, або ще xє в списку правильну кількість разів. Ця функція виплітає деякі помилки, оскільки (наприклад) нам не слід називати xth елемент початкового списку {}; однак, значення все правильно.


4

Python 2, 99 86 байт

Завдяки @Dennis за декілька вдосконалень на загальну суму 13 байт!

s=0,1,2,3
exec't=1\nwhile t==s[-1]or s.count(t)/s[t]:t+=1\ns+=t,;'*input()
print s[-4]

Програма триває досить наївно: вона відслідковує список значень, визначених на даний момент, і шукає додавання наступного значення. Він намагається додати а 1до кінця списку, якщо може; якщо ні, то він намагається 2і так далі, поки щось не дозволено.

Тепер ми почнемо з висіву результатів для того, 1,2,3щоб бути 1,2,3. Це робиться для того, щоб уникнути проблем із переліком вже обчислених значень занадто коротко: я гадаю , що, якщо nпринаймні, 4то a(n)суворо менше n. (У цій програмі s[n]дорівнює a(n). Наш список насправді ініціалізований [0,1,2,3]тому, що списки 0вбудовані в Python. Так, наприклад a(1)=s[1]=1, і a(2)=s[2]=2.)

Отже, скажімо, ми намагаємося визначити s[m], тобто наш список вже включає s[0], s[1], ..., s[m-1]. Ми почнемо з t=1та спробуємо встановити s[m]=1. Коли це не працює, ми переходимо до t=2спроби встановити s[m]=2. Кожен раз, коли ми збільшуємо t, ми перевіряємо, чи s.count(t)==s[t]... але права частина не призведе до помилок, доки ми ніколи не повинні підніматися так високо t=m. Гіпотеза говорить, що нам ніколи цього не доводиться, оскільки перше значення, яке ми обчислюємо, насправді s[4].

Ця реалізація обчислює 3 більше значення послідовності, ніж потрібно. Наприклад, якщо nє 8, він буде обчислюватися до того, s[11]як він поверне значення s[8].

Я був би радий побачити доказ гіпотези. Я вважаю, що це можна довести (сильною?) Індукцією.

Редагувати: Ось доказ гіпотези . Ми фактично доводимо дещо сильнішу форму твердження, оскільки вона не передбачає додаткової роботи.

Теорема: Для всіх nбільших або рівних 4термін a(n)менший або рівний (n-2).

Доказ (по індукції Strong): (Base n=4): Це твердження вірне для n=4, так як a(4) = 2 = 4-2.

Тепер припустимо a(k), що менше або рівне k-2для всіх kвід 4наскрізь n, включно (і припустимо n, щонайменше 4). Зокрема, це означає, що всі попередні умови послідовності були максимум (n-2). Нам потрібно показати, що a(n+1)буде якнайбільше (n-1). Тепер, за визначенням, a(n)це найменше додатне ціле число, яке не порушує жодну з умов, тому нам просто потрібно показати, що значення (n-1)не порушує жодної з умов.

Значення (n-1)не буде порушувати умову "немає послідовних повторів", оскільки за індукційною гіпотезою попередній запис був максимум (n-2). І це не порушить умову " a(m)є кількість разів, що mз'являється", якщо тільки (n-1)не було досягнуто a(n-1)разів. Але, за сильним припущенням індукції, (n-1)раніше були досягнуті 0часи, і a(n-1)це не дорівнює 0тому, що a(m)є позитивним для всіх m.

Тому a(n+1)менше або дорівнює n-1 = (n+1)-2, як бажано. QED.


3

Желе , 17 байт

Ṭ€S<;1Tḟ®Ḣ©ṭ
⁸Ç¡Ṫ

Три останні тестові випадки занадто багато для TIO. Я перевірив 1000 та 1257 локально.

Спробуйте в Інтернеті! або підтвердити перші 100 термінів .

Як це працює

⁸Ç¡Ṫ          Main link. No arguments.

⁸             Yield [].
 Ç¡           Execute the helper link n times (where n is an integer read from
              STDIN), initially with argument [], then with the previous return
              value as argument. Yield the last return value.
              Tail; yield the last element of the result.


Ṭ€S<;1Tḟ®Ḣ©ṭ  Helper link. Argument: A (array)

Ṭ€            Untruth each convert each k into an array of k-1 zeroes and one 1.
  S           Sum; column-wise reduce by +, counting the occurrences of all
              between 1 and max(A).
   <          Compare the count of k with A[k] (1-indexed), yielding 1 for all
              integers that still have to appear once or more times.
    ;1        Append a 1 (needed in case the previous result is all zeroes).
      T       Truth; find all indices of ones.
       ḟ®     Filter-false register; remove the value of the register (initially 0)
              from the previous result.
         Ḣ©   Head copy; yield the first (smallest) value of the result and save
              it in the register.
           ṭ  Tack; append the result to A.

3

Python 2 , 77 74 байт

f=lambda n,k=1:n*(n<4)or map(f,range(n)+k*[n-1]).count(k)<f(k)or-~f(n,k+1)

Це рекурсивна реалізація алгоритму @ mathmandan .

Реалізація є O (божевільна) : введення 9 займає 2 секунди локально, введення 10 52 секунди, а введення 11 17 хвилин і 28 секунд. Однак, якщо оголошено як звичайну функцію, а не лямбда, пам’ятізація може бути використана для перевірки тестових випадків.

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

Зауважте, що навіть при запам'ятовуванні, TIO не може обчислити f (1257) або f (10000) (обидві перевірені локально).


2

05AB1E , 32 31 байт

XˆXˆG[N¯2(è<›¯¤NÊsN¢¯Nè‹&&#]N.ˆ

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

Пояснення

XˆXˆ                             # initialize global list as [1,1]
    G                            # input-1 times do:
     [                    #]     # loop until expression is true     
      N¯2(è<›                    # n > list[-2]-1
             ¯¤NÊ                # list[-1] != N
                 sN¢¯Nè‹         # count(list, N) < list[N]
                        &&       # logical AND of the 3 expressions
                            N.ˆ  # add N to global list 
                                   and output last value in list and end of program

Ми технічно в циклі , Gколи ми додаємо N в глобальний список, але все петлі в 05AB1E використовувати ту ж змінну N як індекс, так що внутрішній контур [...]має переписується N з Gозначає , що ми можемо додати його поза циклом.

Проблеми з вкладеними циклами та умовними умовами заважає нам робити це всередині циклу.


2

Befunge, 141 136 байт

<v9\0:p8\2:*2:-1<9
v>p1+:3\8p0\9p:#^_&
>1-:#v_1.@>$8g.@
*+2%\>1-:!|>$!:::9g!\!9g!*\:8g\!8g`
9\+1g9::< \|`g9\g8+2::p
g2+\8p2+^:<>:0\9p::8

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

Через обмеження пам’яті Befunge не дуже практично відслідковувати всі попередні записи в послідовності, тому для цього рішення використовується алгоритм із нижчим відбитком пам’яті, який обчислює значення більш безпосередньо.

Це означає, що ми все ще обмежені розміром комірки, який у перекладача подій Befunge-93 є підписаним 8-бітовим значенням, тому найбільше підтримуване парне число в послідовності є A(1876) = 126, а найбільше підтримується непарне число A(1915) = 127.

Якщо ви хочете перевірити великі значення, вам потрібно буде використовувати інтерпретатор з більшим розміром комірок. Це повинно включати більшість реалізацій Befunge-98 ( Спробуйте в Інтернеті! ).


0

Python 2, 117 байт

Мех. Не такий короткий. Просте ітеративне рішення.

L=[1,2,3]
n=input()
while len(L)<n:
 for i in range(2,n):
    if L.count(i)<L[i-1]and L[-1]!=i:L+=[i];break
print L[n-1]

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

Ось справді погана спроба рекурсивного рішення (129 байт):

def f(n,L=[1,2,3]):
 if len(L)>=n:print L[n-1];exit(0)
 for i in range(2,n):
    if L.count(i)<L[i-1]and L[-1]!=i:f(n,L+[i])
 f(n,L)

Виправлено. Я думав, що міг би використати -1замість того, n-1щоб зберегти байт, я думаю, що ні.
mbomb007
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.