Phân tích trình tự giống Collatz


12

Chúng tôi xác định chuỗi giống Collatzs với 4 số nguyên dương:

  • n giá trị khởi đầu
  • d > 1 ước số
  • m > 1 số nhân
  • i tăng

(Trong chuỗi Collatz ban đầu d = 2 m = 3i = 1.)

Cho các số nguyên snày sẽ được tạo theo cách sau:

  • s(0) = n
  • nếu k > 0s(k-1) mod d = 0sau đós(k) = s(k-1) / d
  • nếu k > 0s(k-1) mod d != 0sau đós(k) = s(k-1) * m + i

Một chuỗi ví dụ với d = 2, m = 3, i = 5n = 80sẽ được s = 80, 40, 20, 10, 5, 20, 10, 5, 20, ....

Mỗi chuỗi sẽ đạt giá trị cao hơn bất kỳ ràng buộc nào (nghĩa là chuỗi là phân kỳ) hoặc đi vào một vòng lặp vô hạn nếu đối với một số tu( t!=u) s(t) = s(u)đẳng thức sẽ là đúng.

Trong vấn đề của chúng tôi nếu giá trị của phần tử chuỗi lớn hơn 10^9hoặc không có sự lặp lại phần tử trước 1000phần tử thứ thì chuỗi được coi là phân kỳ.

Nhiệm vụ

Bạn nên viết một chương trình hoặc hàm lấy các số nguyên dương d milàm đầu vào và đầu ra tất cả các loại kết thúc khác nhau của chuỗi (vòng lặp vô hạn và phân kỳ) mà các giá trị bắt đầu n = 1, 2, 3, ... 999, 1000có thể tạo ra.

Chi tiết đầu vào

  • Đầu vào là một chuỗi hoặc danh sách (hoặc gần tương đương trong ngôn ngữ của bạn) đại diện (theo cách thông thường) ba số nguyên dương d, mitheo thứ tự đó. dmít nhất 2. Không có số nào lớn hơn 100.

Chi tiết đầu ra

Các đặc điểm kỹ thuật đầu ra là một chút dài dòng. Có thể đáng để kiểm tra các ví dụ đầu tiên.

  • Bạn nên xuất ra đầu ra tiêu chuẩn (hoặc thay thế gần nhất) hoặc trả về một chuỗi.
  • Nếu trình tự phân kỳ có thể thì dòng đầu tiên sẽ là DIVERGENT.
  • Một đại diện duy nhất của vòng lặp là một vòng quay trong đó số nhỏ nhất là số cuối cùng được phân tách bằng dấu cách. Ví dụ: nếu s = 2 1 4 2 1 4 2 1vòng lặp là 4 2 1.
  • Trong mỗi dòng sau, bạn nên xuất ra mỗi vòng lặp duy nhất chính xác một lần trước từ đó LOOP. Ví dụLOOP 4 2 1
  • Các vòng lặp phải theo thứ tự tăng dần về phần tử cuối cùng của chúng.
  • Trailing newline là tùy chọn.

Ví dụ:

Các dòng đầu tiên là đầu vào và các dòng sau cho đến khi một dòng trống là đầu ra.

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

Tham chiếu thực hiện trong Python 3 trên Ideone.

Đây là mã golf để chiến thắng ngắn nhất.

Câu trả lời:


5

Python 3, 269 254 252 246 byte

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])

(Bây giờ chậm hơn 10 lần để tiết kiệm một vài byte. Golf mã điển hình.)

Nhập danh sách qua STDIN (ví dụ [2, 3, 1]). Tôi nghĩ rằng phải có một cách tốt hơn để chuẩn hóa các chu kỳ ...

Cách tiếp cận khá đơn giản - kiểm tra tất cả 1000 số và chỉ lấy các đầu ra duy nhất. Tuy nhiên, có hai thủ thuật nhỏ trong đó:

  • Các vòng lặp được thể hiện bằng các bộ dữ liệu không trống, nhưng quan trọng hơn là sự phân kỳ được thể hiện bằng một bộ dữ liệu trống . Điều này là tốt bởi vì:

    • Nó không bị hỏng sortedvà thậm chí sẽ xuất hiện trước tất cả các bộ vòng lặp
    • Nó cho phép chúng ta chọn một chuỗi thông qua x and"LOOP"or"DIVERGENT"
    • *()[::-1] không ảnh hưởng print
  • Các vòng lặp được xây dựng ngược để biến "sắp xếp tăng dần theo yếu tố cuối cùng" thành "sắp xếp tăng dần theo yếu tố đầu tiên", điều này loại bỏ sự cần thiết phải chuyển lambda vào sorted.

Gửi trước đó, 252 byte

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])

Cái này nhanh hơn nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.