分析类似Collat​​z的序列


12

我们定义具有4个正整数的类Collat​​z序列s

  • n 起始值
  • d > 1 除数
  • m > 1 乘数
  • i 增量

(在原始Collat​​z序列中d = 2 m = 3i = 1。)

给定这些整数s将以以下方式创建:

  • s(0) = n
  • 如果k > 0s(k-1) mod d = 0s(k) = s(k-1) / d
  • 如果k > 0s(k-1) mod d != 0s(k) = s(k-1) * m + i

用一个例子的序列d = 2, m = 3, i = 5n = 80将是s = 80, 40, 20, 10, 5, 20, 10, 5, 20, ...

每个序列将达到比任何给定界限更高的值(即序列是发散的),或者如果对于(t和)相等,则为真,则进入无限循环。ut!=us(t) = s(u)

在我们的问题中,如果序列元素的值大于10^9或在第1000th个元素之前没有元素重复,则该序列被视为发散的。

任务

您应该编写一个程序或函数,该程序或函数采用正整数d m并将其i作为输入并输出起始值n = 1, 2, 3, ... 999, 1000可以产生的序列的所有不同结束类型(无限循环和散度)。

输入详细信息

  • 输入是代表一个字符串或列表(或者在你的语言最接近的等效)(在常见的方式)三位正整数dm并且i按照这个顺序。d并且m至少2。两者都不大于100

输出细节

输出规范有点罗word。可能值得首先查看示例。

  • 您应该输出到标准输出(或最接近的替代品)或返回字符串。
  • 如果可能出现发散序列,则第一行应为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

在Ideone上的Python 3中的参考实现。

这是代码高尔夫球,因此最短的参赛作品会获胜。

Answers:


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
  • 循环是向后构建的,以将“按最后一个元素升序排序”转换为“按第一个元素升序排序”,从而消除了将lambda传递到的需要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])

这个快很多。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.