Collat​​zのようなシーケンスの分析


12

4つの正の整数でCollat​​zのようなシーケンスを定義しsます。

  • n 開始値
  • d > 1 除数
  • m > 1 乗数
  • i インクリメント

(元のCollat​​zシーケンス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 = 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生成することができます。

入力内容

  • 入力文字列またはリスト(またはあなたの言語で、最も近い同等)を表す(一般的な方法で)3つの正の整数でdmかつiその順序で。dm少なくとも2です。どちらの数もより大きいです100

出力の詳細

出力仕様は少し冗長です。最初に例を確認する価値があるかもしれません。

  • 標準出力(または最も近い代替)に出力するか、文字列を返す必要があります。
  • 発散シーケンスが可能な場合、最初の行はである必要がありますDIVERGENT
  • シーケンスのループのユニークな表現は、最小の数字がスペースで区切られた最後の数字である回転です。たとえばs = 2 1 4 2 1 4 2 1、ループがの場合4 2 1
  • 次のすべての行で、単語の前に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のリファレンス実装。

これはコードゴルフなので、最短のエントリーが勝ちます。

回答:


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の数値すべてをテストし、一意の出力のみを取得します。ただし、そこには2つの小さなトリックがあります。

  • ループは空でないタプルで表されますが、さらに重要なことは、分岐は空のタプルで表されます。これは、次の理由により優れています。

    • 壊れず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])

これははるかに高速です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.