Анализ коллатц-подобных последовательностей


12

Мы определяем Коллатц подобную последовательность 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.