Аналіз послідовностей, подібних Колац


12

Визначимо Коллатц послідовність -like sз 4 позитивних цілих чисел:

  • n вихідне значення
  • d > 1 дільник
  • m > 1 множник
  • i приріст

(У початковій послідовності Колац d = 2 m = 3і i = 1.)

З огляду на ці цілі числа sбудуть створені наступним чином:

  • s(0) = n
  • якщо k > 0і s(k-1) mod d = 0тодіs(k) = s(k-1) / d
  • якщо k > 0і s(k-1) mod d != 0тодіs(k) = s(k-1) * m + i

Приклад послідовності з d = 2, m = 3, i = 5і n = 80буде s = 80, 40, 20, 10, 5, 20, 10, 5, 20, ....

Кожна послідовність або досягне більш високих значень, ніж будь-яка задана межа (тобто послідовність розбіжна), або потрапить у нескінченний цикл, якщо для деяких tта u( t!=u) s(t) = s(u)рівність буде істинною.

У нашій проблемі, якщо значення елемента послідовності більше 10^9або немає повторення елемента перед цим 1000елементом, послідовність вважається розбіжною.

Завдання

Вам слід написати програму або функцію, яка приймає натуральні цілі d mі iяк входи, і виводить всі різні типи закінчень послідовностей (нескінченних циклів і розбіжностей), які n = 1, 2, 3, ... 999, 1000можуть створювати вихідні значення .

Деталі введення

  • Вхід - це рядок або список (або найближчий еквівалент вашій мові), що представляє (загальноприйнятим способом) три додатні цілі числа d, mі iв цьому порядку. dі mє принаймні 2. Жодне число не перевищує 100.

Вихідні дані

Вихідна специфікація трохи словна. Варто спочатку перевірити приклади.

  • Вам слід вивести стандартний вихід (або найближчу альтернативу) або повернути рядок.
  • Якщо можлива розбіжна послідовність, перший рядок повинен бути DIVERGENT.
  • Унікальне зображення циклу послідовності - це його обертання, де найменше число є останнім розділеним пробілами. Наприклад, якщо s = 2 1 4 2 1 4 2 1цикл є 4 2 1.
  • У кожному наступному рядку слід виводити кожен унікальний цикл точно один раз перед цим словом LOOP. НапрLOOP 4 2 1
  • Петлі повинні бути у порядку зростання щодо останнього елемента.
  • Новий рядок не є обов'язковим.

Приклади:

Перші рядки - це входи, а наступні - поки порожні рядки не є вихідними.

2 3 1
LOOP 4 2 1

2 2 6
LOOP 8 4 2 1
LOOP 12 6 3

3 7 8
DIVERGENT
LOOP 15 5 43 309 103 729 243 81 27 9 3 1
LOOP 22 162 54 18 6 2
LOOP 36 12 4

3 9 1
DIVERGENT

6 9 9
DIVERGENT
LOOP 18 3 36 6 1
LOOP 27 252 42 7 72 12 2
LOOP 45 414 69 630 105 954 159 1440 240 40 369 3330 555 5004 834 139 1260 210 35 324 54 9 90 15 144 24 4
LOOP 81 738 123 1116 186 31 288 48 8
LOOP 99 900 150 25 234 39 360 60 10
LOOP 126 21 198 33 306 51 468 78 13

10 10 10
LOOP 20 2 30 3 40 4 50 5 60 6 70 7 80 8 90 9 100 10 1

93 91 92
DIVERGENT
LOOP 2185 198927 2139 23
LOOP 4278 46

Реалізація посилань у Python 3 на Ideone.

Це кодовий гольф, тому найкоротший виграш вступу.

Відповіді:


5

Python 3, 269 254 252 246 байт

d,m,i=eval(input())
S=set()
for n in range(1,1001):
 T=X=()
 while len(T)**3<1e9>=n:
  T=(n,)+T;n=[n//d,n*m+i][n%d>0]
  if n in T:I=T.index;L=T[:I(n)+1];M=I(min(L));X=L[M:]+L[:M]
 S|={X}
for x in sorted(S):print(x and"LOOP"or"DIVERGENT",*x[::-1])

(Зараз у 10 разів повільніше, щоб зберегти кілька байт. Типовий код гольфу.)

Введіть список через STDIN (наприклад [2, 3, 1]). Я думаю, що повинен бути кращий спосіб стандартизації циклів ...

Підхід досить простий - протестуйте всі 1000 номерів і беріть лише унікальні результати. Однак є два маленькі хитрощі:

  • Петлі представлені непорожніми кортежами, але важливіше розбіжність представлено порожнім кортежем. Це добре тому, що:

    • Він не зламається sortedі навіть з’явиться перед усіма петлями циклу
    • Це дозволяє нам вибрати рядок через x and"LOOP"or"DIVERGENT"
    • *()[::-1] не впливає print
  • Петлі побудовані назад, щоб перетворити "сортування за зростанням за останнім елементом" в "сортування за зростанням за першим елементом", що знімає необхідність передавати лямбда sorted.

Попереднє подання, 252 байти

d,m,i=eval(input())
def f(n,T=()):
 x=[n//d,n*m+i][n%d>0];I=T.index
 if x in T:L=T[:I(x)+1];M=I(min(L));return L[M:]+L[:M]
 return()if(T[1000:]or x>1e9)else f(x,(x,)+T)
for x in sorted(set(map(f,range(1,1001)))):print(x and"LOOP"or"DIVERGENT",*x[::-1])

Це набагато швидше.

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