Dugaan Collatz Rekursif


21

The Collatz dugaan postulat bahwa jika Anda mengambil setiap bilangan bulat positif, kemudian ulangi algoritma berikut cukup kali:

if number is odd, then multiply by three and add one
if number is even, then divide by two

Anda akhirnya akan berakhir pada 1. Tampaknya selalu berfungsi, tetapi tidak pernah terbukti bahwa selalu berhasil.

Anda telah bermain golf menghitung berapa lama untuk sampai ke 1 , jadi saya pikir saya akan sedikit beralih.

Dimulai dengan bilangan bulat positif yang diberikan, hitung berapa lama untuk mencapai 1 ("waktu berhenti"). Kemudian menemukan bahwa waktu berhenti nomor ini.

Ulangi sampai Anda mencapai 1, atau sampai Anda mencapai batas 100 iterations sepenuhnya sewenang-wenang. Dalam kasus sebelumnya, cetak berapa banyak iterasi yang diperlukan. Dalam kasus terakhir, cetak "Gagal" atau output konsisten pilihan Anda, selama itu bukan bilangan bulat 1≤n≤100. Anda tidak boleh mengeluarkan string kosong untuk opsi ini. Akan tetapi, menghasilkan bilangan bulat di luar kisaran [1, 100].

Contoh:

Input: 2
2->1
Output: 1

Input: 5
5->5->5->5->5->...
Output: Fail

Input: 10
10->6->8->3->7->16->4->2->1
Output: 8

Input: 100
100->25->23->15->17->12->9->19->20->7->16->4->2->1
Output: 13

Input: 10^100
10^100->684->126->108->113->12->9->19->20->7->16->4->2->1
Output: 13

Input: 12345678901234567890
12345678901234567890->286->104->12->9->19->20->7->16->4->2->1
Output: 11

Input: 1
--Depending on your code, one of two things may happen. Both are valid for the purposes of this question.
1
Output: 0
--Or:
1->3->7->16->4->2->1
Output: 6

Saat saya menghitung 10^100dan 12345678901234567890menggunakan bahasa yang hanya mendukung real untuk ukuran itu, jika bahasa Anda lebih akurat, Anda mungkin mendapatkan hasil berbeda untuk itu.

Mencetak gol

Karena ini adalah , jawabannya dengan jumlah byte terpendek akan menang.


Jawaban:




6

Attache , 40 byte

`-&3@`#@PeriodicSteps[CollatzSize@Max&1]

Cobalah online!

Ini adalah bahasa baru yang saya buat. Saya ingin berkeliling untuk membuat bahasa infiks yang tepat, dan ini adalah hasilnya: sebuah matematik knock-off. Hore?

Penjelasan

Ini adalah komposisi dari beberapa fungsi. Fungsi-fungsi ini adalah:

  • PeriodicSteps[CollatzSize@Max&1]Ini menghasilkan fungsi yang menerapkan argumennya hingga hasilnya berisi elemen duplikat. Fungsi ini,, CollatzSize@Max&1diterapkan CollatzSizepada input yang lebih besar dan 1, untuk menghindari input yang tidak valid 0ke CollatSize.
  • `#adalah operator yang dikutip; ketika diterapkan secara monadik dalam pengertian ini, ia memperoleh ukuran argumennya
  • `-&3adalah fungsi terikat, yang mengikat argumen 3ke fungsi `-, yang berbunyi "minus 3". Ini karena aplikasi PeriodicSteps menghasilkan 0, yang perlu dipertanggungjawabkan. (Ini juga dengan rapi menangani angka di luar batas seperti 5, yang dipetakan ke -1.)

1
Apakah menggunakan bahasa Anda sendiri benar-benar diizinkan? Tidak bisakah kamu membuat langage untuk setiap codegolf dengan hanya menggunakan beberapa byte?
Tweakimp

2
@Tweakimp Tentu saja membuat (dan menggunakan) bahasa Anda sendiri diperbolehkan. Tetapi memodifikasinya sehingga tugas adalah perintah tunggal (setelah tantangan diposting) adalah celah standar.
caird coinheringaahing

2
@Tweakimp jika itu membuat Anda merasa lebih baik, saya telah merancang fungsi ini sebelum saya melihat tantangan ini. Saya seorang desainer bahasa, jadi itulah yang saya lakukan.
Conor O'Brien

Itu lebih merupakan pertanyaan umum apakah bahasa buatan sendiri diizinkan, bukan pernyataan negatif yang Anda gunakan sendiri.
Tweakimp

4

J , 49 45 byte

-4 byte berkat kode Sequence Collatz yang lebih pendek yang diambil dari komentar @ randomra di sini .

(2-~[:#(>&1*-:+2&|*+:+>:@-:)^:a:)^:(<101)i.1:

Output 101untuk hasil yang tidak valid.

Cobalah online!

Penjelasan

Tidak mengherankan, penjelasan ini menjadi cepat usang. Saya akan meninggalkannya dalam hal jawaban 49 byte lama yang saya miliki, yang saya sertakan di bawah ini. Jika Anda ingin pembaruan, beri tahu saya. Cara menemukan panjang urutan rekursif tetap sama, saya baru saja menggunakan metode Urutan Collatz pendek.

(1-~[:#%&2`(1+3&*)@.(2&|)^:(1&<)^:a:)^:(<101)i.1:

Menemukan panjang Urutan Collatz

Bagian kode ini adalah sebagai berikut

(1-~[:#%&2`(1+3&*)@.(2&|)^:(1&<)^:a:)

Inilah penjelasannya:

(1 -~ [: # %&2`(1+3&*)@.(2&|) ^: (1&<) ^: a:)  Given an input n
                                       ^: a:   Apply until convergence, collecting
                                                each result in an array.
                              ^: (1&<)         If n > 1 do the following, else
                                                return n.
                        (2&|)                  Take n mod 2.
           %&2                                 If n mod 2 == 0, divide by 2.
               (1+3&*)                         If n mod 2 == 1, multiply by 3 
                                                and add 1.
         #                                     Get the length of the resulting
                                                array.
 1 -~                                          Subtract 1.

Sayangnya, kata kerja yang berlaku ( ^:) saat disuruh menyimpan hasil menyimpan nilai awal juga, jadi itu berarti kami (seperti biasa) tidak aktif satu per satu. Karenanya mengapa kita mengurangi 1.

Menemukan panjang urutan rekursif

(1-~[:#%&2`(1+3&*)@.(2&|)^:(1&<)^:a:) ^: (< 101) i. 1:  Given an input n.
                                      ^: (< 101)        Apply 100 times,
                                                         collecting results
                                                         in an array.
(1-~[:#%&2`(1+3&*)@.(2&|)^:(1&<)^:a:)                   Collatz sequence length.
                                                 i. 1:  Index of first 1 (returns
                                                         101, the length of the
                                                         array if 1 not found).

1
Jika Anda tidak keberatan menggunakan bagian tajuk, ini mungkin akan lebih akurat menampilkan jawaban Anda
Conor O'Brien

@ ConorO'Brien Saya sama sekali tidak - saya tidak benar-benar tahu cara memformatnya (tapi saya akan mencuri milik Anda mulai sekarang). Terima kasih
cole

1
A n y t i m e!
Conor O'Brien

1
38 byte dengan *i.~(<101)1&(#@}.a:2&(<*|{%~,*+1+])])]harus sama
mil

4

C (gcc) , 75 byte

i,j;f(n){for(j=0;(i=n)&&j++<100;)for(n=0;i-1;++n)i=i&1?i*3+1:i/2;i=!i*j-1;}

Pengembalian -1untuk n>=100iterasi.

Cobalah online!

C (gcc) , 73 byte

i,j;f(n){for(j=-1;(i=n)&&j++<99;)for(n=0;i-1;++n)i=i&1?i*3+1:i/2;i=!i*j;}

Pengembalian 0untuk n>=100iterasi.

Cobalah online!


3

JavaScript (ES6), 57 byte

Kembali trueketika gagal. Pengembalian 0untuk 1.

f=(n,k=i=0)=>n>1?f(n&1?n*3+1:n/2,k+1):k?i>99||f(k,!++i):i

Uji kasus


Saya ragu apakah program Anda menghitung hasil yang benar selain dari overflow / ketidaktepatan atau jika OP mendapatkan hasil mereka menggunakan bahasa dengan implementasi angka yang sama (saya berasumsi mereka tidak menghitung semua kasus uji dengan tangan).
Jonathan Frech

@JonathanFrech Memang. Ternyata kedua hasil itu sama-sama tidak valid.
Arnauld

3

APL (Dyalog Unicode) , 39 60 53 52 49 byte

-3 byte terima kasih kepada @ngn

0∘{99<⍺:⋄1=⍵:01+(⍺+1)∇{1=⍵:01+∇⊃⍵⌽0 1+.5 3×⍵}⍵}

Cobalah online!

Menggunakan kode @ngn untuk Collatz, tetapi sebelumnya menggunakan kode @ Uriel.

Inilah versi lama yang tidak memenuhi spesifikasi:

{1=⍵:01+∇{1=⍵:02|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}⍵}

2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2->1+∇⊃⍵⌽0 1+.5 3×⍵
ngn


2

Sekam , 21 byte

←€1↑101¡ȯ←€1¡?½o→*3¦2

Cobalah online! Pengembalian -1saat gagal, 0saat input 1.

Penjelasan

←€1↑101¡ȯ←€1¡?½o→*3¦2  Implicit input (a number).
             ?½o→*3¦2  Collatz function:
             ?     ¦2   if divisible by 2,
              ½         then halve,
               o→*3     else multiply by 3 and increment.
        ȯ←€1¡?½o→*3¦2  Count Collatz steps:
            ¡           iterate Collatz function and collect results in infinite list,
          €1            get 1-based index of 1,
        ȯ←              decrement.
       ¡               Iterate this function on input,
   ↑101                take first 101 values (initial value and 100 iterations),
←€1                    get index of 1 and decrement.

2

C (gcc) , 70 73 byte

g(x){x=x-1?g(x%2?3*x+1:x/2)+1:0;}f(x,m){for(m=0;(x=g(x))&&100>m++;);x=m;}

Cobalah online!

Kembali 101ketika jumlah iterasi melebihi 100.


1
Selamat datang di PPCG! Jawaban ini tidak cukup valid, karena semua pengiriman fungsi harus dapat digunakan kembali . Saya pikir Anda dapat memperbaikinya dengan memasukkan m=0ke dalam Anda f(bahkan mungkin menggunakan forintiailiser yang saat ini kosong untuk menyimpan satu a ;).
Martin Ender

2

Bersih , 146 ... 86 byte

-11 byte berkat Ørjan Johansen

import StdEnv
?f l n=hd[u\\1<-iterate f n&u<-l]

?(?(\b|isOdd b=3*b+1=b/2)[0..])[0..99]

Sebagai fungsi parsial literal.

Cobalah online!

Batalkan dengan hd of []jika jumlah iterasi melebihi 100.
Keluar dengan Heap Fulluntuk input di atas ~ 2^23kecuali jika Anda menentukan ukuran tumpukan yang lebih besar.


1
Saya mulai memahami beberapa sintaksis Bersih (karena berbeda dari Haskell) dari jawaban Anda ... Anda dapat mempersingkatnya dengan fungsi pembantu j f l n=hd[u\\1<-iterate f n&u<-l].
Ørjan Johansen

@ ØrjanJohansen Terima kasih!
Kamis

Anda tidak perlu \a=...abagian, itu kari. (Atau mengurangi eta.)
Ørjan Johansen

@ ØrjanJohansen oh, melewatkannya, terima kasih!
Kamis

1

Python 2 , 99 98 97 byte

  • Menyimpan byte dengan menggunakan c and t or falih-alih t if c else f.
  • Menyimpan byte dengan keluaran -1alih-alih fatau 'f'untuk input yang tidak berhenti.
exec"f,F="+"lambda n,i=0:n<2and i or %s"*2%("f([n/2,3*n+1][n%2],-~i),","i>99and-1or F(f(n),-~i)")

Cobalah online!


1

BiwaScheme , 151 karakter

(define(f n i s)(if(= s 0) 'F(if(= n 0)i(f(letrec((c(lambda(m k)(if(= m 1)k(c(if(=(mod m 2)0)(/ m 2)(+(* m 3)1))(+ k 1))))))(c n 0))(+ i 1)(- s 1)))))

Anda bisa mencobanya di sini .


1

R , 119 107 byte

Sebagian menggunakan kode collatz Jarko Dubbeldam dari sini . Pengembalian 0untuk> 100 iterasi (kegagalan).

pryr::f(x,{N=n=0
while(x-1){while(x-1){x=`if`(x%%2,3*x+1,x/2);n=n+1}
x=n
n=0
N=N+1
if(N==100)return(0)}
N})

Cobalah online!


1

APL NARS, 115 byte, 63 karakter

{d←0⋄{⍵=1:d⋄99<d+←1:¯1⋄∇{c←0⋄{1=⍵:c⋄c+←1⋄2∣⍵:∇1+3×⍵⋄∇⍵÷2}⍵}⍵}⍵}

Mungkin menggunakan loop itu akan lebih jelas ... Ada 4 fungsi, 2 bersarang dan retorif, dan yang pertama hanya untuk mendefinisikan dan menginisialisasi ke = 0, variabel d, dilihat dari fungsi ke-2 sebagai penghitung variabel global.

q←{c←0⋄{1=⍵:c⋄c+←1⋄2∣⍵:∇1+3×⍵⋄∇⍵÷2}⍵}

Fungsi ke-3 ini, akan menjadi fungsi yang mengembalikan berapa banyak panggilan yang ada untuk menyelesaikan dugaan Collatz untuk argumennya

{⍵=1:d⋄99<d+←1:¯1⋄∇q⍵}

Ini adalah fungsi ke-2, jika memiliki arg = 1, hentikan rekursi dan kembalikan jumlah waktu yang disebut dengan dirinya sendiri-1; lain jika itu sendiri disebut lebih dari 99 kali menghentikan rekursi dan mengembalikan -1 (gagal) lain menghitung dugaan Collatz untuk argumennya, dan menyebut dirinya untuk nilai panjang urutan Collatz. Bagi saya bahkan jika semua ini tampaknya berjalan bisa menjadi masalah besar jika didefinisikan sebagai variabel global dan satu variabel dalam fungsi dengan nama yang sama, ketika programmer melihatnya hanya sebagai variabel lokal.

  f←{d←0⋄{⍵=1:d⋄99<d+←1:¯1⋄∇{c←0⋄{1=⍵:c⋄c+←1⋄2∣⍵:∇1+3×⍵⋄∇⍵÷2}⍵}⍵}⍵}     
  f 2
1
  f 3
5
  f 5
¯1
  f 10
8
  f 100
13
  f 12313
7
  f 1
0

1

(Emacs, Common, ...) Lisp, 105 byte

Pengembalian t untuk iterasi> 100

(defun f(n k c)(or(> c 100)(if(= n 1)(if(= k 0)c(f k 0(1+ c)))(f(if(oddp
n)(+ n n n 1)(/ n 2))(1+ k)c))))

Diperluas:

(defun f (n k c)
  (or (> c 100)
      (if (= n 1)
          (if (= k 0) c
            (f k 0 (1+ c)))
        (f (if (oddp n) (+ n n n 1) (/ n 2))
           (1+ k) c))))
(f (read) 0 0)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.