Menganalisis urutan seperti Collatz

12

Kami mendefinisikan urutan seperti Collatzs dengan 4 bilangan bulat positif:

  • n nilai awal
  • d > 1 pembagi
  • m > 1 pengganda
  • i kenaikan

(Dalam urutan Collatz asli d = 2 m = 3dan i = 1.)

Mengingat bilangan bulat ini sakan dibuat dengan cara berikut:

  • s(0) = n
  • jika k > 0dan s(k-1) mod d = 0kemudians(k) = s(k-1) / d
  • jika k > 0dan s(k-1) mod d != 0kemudians(k) = s(k-1) * m + i

Contoh urutan dengan d = 2, m = 3, i = 5dan n = 80akan s = 80, 40, 20, 10, 5, 20, 10, 5, 20, ....

Setiap urutan akan mencapai nilai yang lebih tinggi daripada batas tertentu (yaitu urutannya berbeda) atau masuk ke loop tak terbatas jika untuk beberapa tdan u( t!=u) s(t) = s(u)kesetaraan akan benar.

Dalam masalah kami jika nilai elemen urutan lebih besar dari 10^9 atau tidak ada pengulangan elemen sebelum 1000elemen th urutan dianggap berbeda.

Tugas

Anda harus menulis sebuah program atau fungsi yang mengambil bilangan bulat positif d mdan isebagai input dan output semua jenis akhir yang berbeda dari urutan (loop tak terhingga dan divergensi) yang nilai awalnyan = 1, 2, 3, ... 999, 1000 dapat dihasilkan oleh .

Detail input

  • Input adalah string atau daftar (atau setara terdekat dalam bahasa Anda) mewakili (dengan cara umum) tiga bilangan bulat positif d, mdan idalam urutan itu. ddan msetidaknya 2. Angka keduanya tidak lebih besar dari 100.

Rincian keluaran

Spesifikasi output agak bertele-tele. Layak untuk memeriksa contoh terlebih dahulu.

  • Anda harus output ke output standar (atau alternatif terdekat) atau mengembalikan string.
  • Jika urutan divergen dimungkinkan, baris pertama seharusnya DIVERGENT.
  • Representasi unik dari loop urutan adalah rotasi itu di mana angka terkecil adalah yang terakhir dipisahkan oleh spasi. Misal jika s = 2 1 4 2 1 4 2 1loop 4 2 1.
  • Di setiap baris berikut Anda harus menampilkan setiap loop unik tepat sekali didahului oleh kata LOOP. MisalnyaLOOP 4 2 1
  • Loop harus dalam urutan menaik sehubungan dengan elemen terakhir mereka.
  • Mengejar baris baru adalah opsional.

Contoh:

Baris pertama adalah input dan yang berikutnya sampai baris kosong adalah output.

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

Referensi implementasi di Python 3 pada Ideone.

Ini adalah kode-golf sehingga entri terpendek menang.

randomra
sumber

Jawaban:

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

(Sekarang 10 kali lebih lambat untuk menyimpan beberapa byte. Golf kode biasa.)

Masukkan daftar melalui STDIN (mis [2, 3, 1] .). Saya berpikir bahwa harus ada cara yang lebih baik untuk menstandarkan siklus ...

Pendekatannya cukup mudah - uji semua angka 1000 dan hanya mengambil output unik. Namun, ada dua trik kecil di sana:

  • Loop diwakili oleh tuple kosong, tetapi yang lebih penting divergensi diwakili oleh tuple kosong . Ini bagus karena:

    • Itu tidak pecah sorted, dan bahkan akan muncul sebelum semua loop tuple
    • Ini memungkinkan kami untuk memilih string melalui x and"LOOP"or"DIVERGENT"
    • *()[::-1] tidak mempengaruhi print
  • Loop dibuat mundur untuk mengubah "urutkan naik dengan elemen terakhir" menjadi "urutkan naik dengan elemen pertama", yang menghilangkan kebutuhan untuk meneruskan lambda ke dalam sorted.

Pengajuan sebelumnya, 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])

Yang ini jauh lebih cepat.

Sp3000
sumber