Phỏng đoán Collatz (OEIS A006577)


66

Đây là Giả thuyết Collatz (OEIS A006577 ):

  • Bắt đầu với số nguyên n > 1.
  • Lặp lại các bước sau:
    • Nếu n chẵn, chia nó cho 2.
    • Nếu n là số lẻ, nhân nó với 3 và thêm 1.

Người ta chứng minh rằng với tất cả các số nguyên dương lên tới 5 * 2 60 , hoặc khoảng 5764000000000000000 , n cuối cùng sẽ trở thành 1 .

Nhiệm vụ của bạn là tìm ra số lần lặp (mất một nửa hoặc gấp ba lần) để đạt được 1 lần .

Xkcd có liên quan :)

Quy tắc:

  • Mã ngắn nhất sẽ thắng.
  • Nếu một số <2 là đầu vào, hoặc không phải là số nguyên hoặc không phải là số, thì đầu ra không thành vấn đề.

Các trường hợp thử nghiệm

2  -> 1
16 -> 4
5  -> 5
7  -> 16

Câu trả lời:



15

C - 50 47 ký tự

Thật không may, C không may đòi hỏi một lượng mã khủng khiếp cho I / O cơ bản, vì vậy việc rút ngắn tất cả những điều đó đã khiến UI hơi không trực quan.

b;main(a){return~-a?b++,main(a&1?3*a+1:a/2):b;}

Biên dịch nó với ví dụ gcc -o 1 collatz.c. Đầu vào là đơn nhất với các chữ số được phân tách bằng dấu cách và bạn sẽ tìm thấy câu trả lời trong mã thoát. Một ví dụ với số 17:

$> ./1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
$> echo $?
12
$>

1
return~-a?tiết kiệm 1. Cũng chuyển b++sang ?trường hợp nên tiết kiệm b--.
ugoren

Hehe bạn đang bẻ cong các quy tắc rất nhiều: P +1 cho sự sáng tạo và sử dụng ngôn ngữ không thường được sử dụng để chơi gôn
Doorknob

Cảm ơn bạn xấu xí! Tôi đã phải say khi viết nó. :)
Dành cho

12

Perl 34 (+1) ký tự

$\++,$_*=$_&1?3+1/$_:.5while$_>1}{

Lạm dụng $\cho đầu ra cuối cùng, như thường lệ. Chạy với -ptùy chọn dòng lệnh, đầu vào được lấy từ stdin.

Đã lưu một byte do Elias Van Ootegem . Cụ thể, quan sát rằng hai sau đây là tương đương:

$_=$_*3+1
$_*=3+1/$_

Mặc dù dài hơn một byte, nhưng nó tiết kiệm được hai byte bằng cách rút ngắn $_/2lại .5.

Sử dụng mẫu:

$ echo 176 | perl -p collatz.pl
18

PHP 54 byte

<?for(;1<$n=&$argv[1];$c++)$n=$n&1?$n*3+1:$n/2;echo$c;

Kiến trúc sư của Javascript cho Giải thưởng Chiếc thìa gỗ dường như đã giảm một chút trong thử thách này. Dù vậy, không có nhiều chỗ cho sự sáng tạo với vấn đề này. Đầu vào được lấy làm đối số dòng lệnh.

Sử dụng mẫu:

$ php collatz.php 176
18

1
Mất một lúc để tìm hiểu những dấu ngoặc chưa từng có đang làm :)
marinus

1
Lặp đi lặp lại $_trong ternary có vẻ lãng phí, bạn có thể loại bỏ một nhân vật khác bằng cách sử dụng *=như thế này : $\++,$_*=$_&1?3+1/$_:.5while$_>1}{. Nhân với 1/$_có tác dụng tương tự +1, vì vậy $_*=3+1/$_hoạt động tốt
Elias Van Ootegem

@EliasVanOotegem $_*=3+1/$_thật tuyệt vời, cảm ơn!
Primo

11

Toán học (35)

If[#>1,#0@If[OddQ@#,3#+1,#/2]+1,0]&

Sử dụng:

If[#>1,#0[If[OddQ@#,3#+1,#/2]]+1,0]&@16
>> 4

Đây không phải là một chức năng hợp lệ, 10.3 phàn nàn về một kẻ lừa đảo @ ở cuối
CalculatorFeline

@ Đang kêu gọi lập luận, tôi không biết tại sao nó đã có, chỉ cần nhanh chóng chỉnh sửa một
dặm

Hãy cẩn thận :)
Máy

10

Như tôi thường làm, tôi sẽ bắt đầu câu trả lời bằng chính mình.

JavaScript, 46 44 ký tự (chạy trên bảng điều khiển)

for(n=prompt(),c=1;n>1;n=n%2?n*3+1:n/2,++c)c

Điểm của ~ ~ prompt () nếu bạn nói đầu ra không quan trọng nếu nó không phải là số nguyên? Bạn có thể lưu hai nhân vật bằng cách loại bỏ ~ ~.
Resorath

@Resorath Ah, quên mất việc truyền tự động của JS: P cảm ơn
Doorknob

9

Java, 165, 156, 154,134,131,129,128 , 126 (ngôn ngữ dài dòng cũng cần một số tình yêu)

class a{public static void main(String[]a){for(int x=Short.valueOf(a[0]),y=0;x>1;x=x%2<1?x/2:x*3+1,System.out.println(++y));}}

Tất cả được thực hiện bên trong

for(int x=Short.valueOf(a[0]),y=0;x>1;x=x%2<1?x/2:x*3+1,System.out.println(++y))

Đó là người đàn ông đẹp tuyệt vời. Cảm ơn Pater Taylor !!!, và ý tưởng sử dụng vòng lặp for đã bị đánh cắp từ ugoren

Tôi đã thay thế Integer cho Short.


1
Bạn có thể khá dễ dàng lưu chiều dài i(,++y). Bạn có thể tiết kiệm thêm hai bằng cách sử dụng <thay vì ==.
Peter Taylor

@PeterTaylor bạn nói đúng, các so sánh của tôi sẽ ngắn hơn với <, nhưng tôi không hiểu phần tăng trước
jsedano

2
Hai mặt của ternary thứ hai của bạn giống hệt nhau về mặt cấu trúc, vì vậy bạn có thể đẩy ternary vào đối số đầu tiên của lệnh gọi đệ quy.
Peter Taylor

1
OH MY THIÊN CHÚA
R BR RÀNG

2
Tôi biết nó đã được khoảng 3,5 năm, nhưng bạn vẫn có thể chơi golf nó bằng 5 byte : class a{public static void main(String[]a){for(int x=new Short(a[0]),y=0;x>1;System.out.println(++y))x=x%2<1?x/2:x*3+1;}}Thay đổi được thực: 1) Thay thế Short.valueOf(...)bằng new Short(...)cho -4 byte và 2) Tôi đã đặt x=x%2<1?x/2:x*3+1;trong cơ thể của for-loop để thoát khỏi sự dấu phẩy cho -1 byte .
Kevin Cruijssen

9

Rebmu : 28

u[++jE1 AeEV?a[d2A][a1M3a]]j

Đối với một vấn đề ngắn gọn và toán học này, GolfScript có thể sẽ giành chiến thắng một phần trăm trước Rebmu (nếu không bắt buộc phải nói, hãy đọc các tệp từ internet hoặc tạo tệp JPG). Tuy nhiên, tôi nghĩ rằng hầu hết sẽ đồng ý logic của Golfscript không dễ theo dõi và tổng số ngăn xếp thực thi đang chạy nó lớn hơn.

Mặc dù người sáng tạo của Rebol, Carl Sassenrath, nói với tôi rằng anh ta thấy Rebmu "không thể đọc được", anh ta đang bận rộn và không có thời gian để thực sự biến đổi giống như lợn-Latin thông qua việc không bị xáo trộn . Điều này thực sự chỉ được chuyển đổi thành:

u [
    ++ j
    e1 a: e ev? a [
        d2 a
    ] [
        a1 m3 a
    ]
]
j

Lưu ý rằng không gian được yêu cầu để có a: thay vì a . Đây là một "từ-set!" và người đánh giá thông báo loại ký hiệu đó để kích hoạt gán.

Nếu nó được viết bằng chữ viết tắt (Rebol viết lúng túng), bạn sẽ nhận được:

until [
    ++ j
    1 == a: either even? a [
        divide a 2
    ] [
        add 1 multiply 3 a
    ]
 ]
 j

Rebol, giống như Ruby, đánh giá các khối đến giá trị cuối cùng của chúng. Vòng lặp UNTIL là một dạng vòng lặp tò mò không có điều kiện vòng lặp, nó chỉ dừng vòng lặp khi khối của nó ước tính thành một cái gì đó không phải là FALSE hoặc KHÔNG. Vì vậy, tại thời điểm 1 ==kết quả của việc gán A (đối số cho rebmu) cho kết quả của điều kiện Collatz (hoặc là IF-ELSE đánh giá cho nhánh mà nó chọn) ... vòng lặp bị phá vỡ.

J và K được khởi tạo thành giá trị nguyên bằng 0 trong Rebmu. Và như đã nói ở trên, toàn bộ điều đánh giá đến giá trị cuối cùng. Vì vậy, một tham chiếu J ở cuối chương trình có nghĩa là bạn có được số lần lặp.

Sử dụng:

>> rebmu/args [u[++jE1 AeEV?a[d2A][a1M3a]]j] 16
== 4

8

Python thay thế, 48

Tôi không tin rằng không có biểu hiện ngắn hơn n=3*n+1;n/=1+n%2*5;. Có lẽ tôi đã tìm thấy hàng tá biểu thức khác nhau có cùng độ dài ...

i=0
n=input()
while~-n:n=3*n+1;n/=1+n%2*5;i+=1
i

chỉnh sửa: Tôi đã tìm thấy một giải pháp khác sẽ không bao giờ tranh cãi, nhưng quá vui khi không chia sẻ.

s='s'
i=s
n=i*input()
while 1:
 while n==n[::2]+n[::2]:i+=s;n=n[::2]
 if n==s:i.rindex(s);break
 n=3*n+s
 i+=s

1
Não tôi đau bây giờ.
daniero

1
@daniero giải pháp thứ hai chỉ dành cho bạn.
gian hàng

Tuyệt vời. Tôi rất vinh dự!
daniero

4
(n//2,n*3+1)[n%2]ngắn hơn
Evpok

1
@Evpok sẽ không n/2hoạt động tốt như chúng ta biết nó là chẵn?
george

7

APL (31)

A←0⋄A⊣{2⊤⍵:1+3×⍵⋄⍵÷2}⍣{⍺=A+←1}⎕

Tuy nhiên, câu trả lời cũ, 27:{1=⍵:0⋄2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}
Uriel

1
{1=⍵:0⋄1+∇⊃⍵⌽0 1+.5 3×⍵}
ngn

7

J, 30 ký tự

<:#-:`(1+3&*)`]@.(2&|+1&=)^:a:

Hóa ra khá lâu hơn một chút so với mong muốn

sử dụng:

   <:#-:`(1+3&*)`]@.(2&|+1&=)^:a:2
1
   <:#-:`(1+3&*)`]@.(2&|+1&=)^:a:16
4
   <:#-:`(1+3&*)`]@.(2&|+1&=)^:a:5
5
   <:#-:`(1+3&*)`]@.(2&|+1&=)^:a:7
16
   <:#-:`(1+3&*)`]@.(2&|+1&=)^:a:27
111
  • -:`(1+3&*)`]là một gerund bao gồm ba động từ, được sử dụng trong ba lần. -:có nghĩa là "giảm một nửa" (1+3&*)hoặc (1+3*])mã hóa bước nhân và ](nhận dạng) hỗ trợ chấm dứt.

  • 2&|+1&=tạo thành một chỉ mục cho gerund. theo nghĩa đen, "phần còn lại sau khi chia cho hai cộng với cho dù nó bằng một".

  • #verb^:a:Lặp lại hàm cho đến khi kết quả ổn định (ở đây, bắt buộc rõ ràng), trong khi thu thập các bước, sau đó đếm chúng. Bị đánh cắp từ @JB . <:giảm số bước từng bước để phù hợp với các yêu cầu câu hỏi.


6
Bất cứ khi nào tôi thấy một bài nộp J, tôi đếm những nụ cười. Cái này làm khá tốt: <:, #-:, :`(, &*), =), )^:.
Primo

3
@primo đẹp; muốn giải thích của họ? :-) <:có nghĩa là "giảm" hoặc "ít hơn hoặc bằng", #có nghĩa là "đếm" hoặc "n lần", -:có nghĩa là "một nửa" hoặc "đẳng thức epsilon", :`(có nghĩa là lần lượt kết thúc của "một nửa", liên kết giữa hai động từ trong một gerund và dấu ngoặc đơn bên trái (được sử dụng để nhóm). &*)có nghĩa là "sth. liên kết với phép nhân" (3 liên kết với phép nhân tạo toán tử "lần ba") và kết thúc nhóm. =thực hiện kiểm tra bình đẳng hoặc, theo nghĩa đơn nhất, tự phân loại. ^:là sự kết hợp sức mạnh (lặp động từ). Vì rất nhiều động từ J kết thúc bằng dấu hai chấm, ... :-)
John Dvorak

Nhiều năm sau ... Khối vòng lặp được cải thiện: '- & 2 # (> & 1 * -: + 2 & | * +: +>: @ - :) ^: a:' -> -1 char. : P
ngẫu nhiên

Nhiều năm sau ... <:#a:2&(<*|+|6&*%~)19 byte (-11)
dặm

6

Lược đồ Gambit, 106 98 ký tự, 40 dấu ngoặc đơn

(let((f(lambda(x)(cond((= x 1) 0)((odd? x)(+ 1(f(+ 1(* 3 x)))))(else(+ 1(f(/ x 2))))))))(f(read)))

91 89 ký tự với định nghĩa trực tiếp

(define(f x)(cond((= x 1)0)((odd? x)(+ 1(f(+ 1(* 3 x)))))(else(+ 1(f(/ x 2))))))(f(read))


Tôi đã không có mặt trong một thời gian dài, nhưng tôi nhận thấy rằng mọi người thường đăng 1 câu trả lời cho mỗi ngôn ngữ lập trình.
jsedano

Xin lỗi, tôi đã không nhận thức được điều đó :)
Valentin CLMENT

Đã chỉnh sửa để xóa Python.
CLIN Valentin ngày

1
Không đúng! Mọi người có xu hướng đăng một câu trả lời cho mỗi ngôn ngữ lập trình, nhưng đó là vì họ đang cố gắng không cạnh tranh trực tiếp với người khác bằng một câu trả lời ngắn hơn. Nhưng không ai sẽ phàn nàn nếu bạn đăng một câu trả lời khác nhau trong cùng một ngôn ngữ.
hộp bánh mì

@breadbox không đúng. Tôi đăng một câu trả lời cho mỗi ngôn ngữ nếu mỗi giải pháp đó thú vị so với các ngôn ngữ khác. Nếu cả hai giải pháp đều thú vị như cả hai cùng nhau (cùng một thuật toán, không có thủ thuật ngôn ngữ thú vị nào), tôi sẽ đăng chúng thành một. Thông thường tôi không đăng nhiều giải pháp vì tôi chọn một ngôn ngữ trước, sau đó giải quyết vấn đề bằng ngôn ngữ đó - sau đó tôi thường quá lười để viết cùng một ngôn ngữ khác - hoặc tôi bắt đầu hành trình tìm hiểu một chương trình khác ngôn ngữ.
John Dvorak

6

PowerShell: 77 74 71 70 61

Mã đánh gôn:

for($i=(read-host);$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x

Ghi chú:

Ban đầu tôi đã thử lấy đầu vào của người dùng mà không buộc nó thành một số nguyên, nhưng điều đó đã phá vỡ một cách thú vị. Bất kỳ đầu vào lẻ ​​nào cũng sẽ xử lý không chính xác, nhưng ngay cả đầu vào cũng hoạt động tốt. Phải mất một phút để tôi nhận ra chuyện gì đang xảy ra.

Khi thực hiện phép nhân hoặc bổ sung, PowerShell xử lý đầu vào chưa gõ dưới dạng chuỗi trước tiên. Vì vậy, '5'*3+1trở thành '5551' thay vì 16. Các đầu vào chẵn hoạt động tốt vì PowerShell không có hành động mặc định để phân chia theo chuỗi. Ngay cả các đầu vào chẵn sẽ phát triển thông qua các số lẻ vẫn hoạt động tốt bởi vì vào thời điểm PowerShell có một số lẻ trong vòng lặp, biến số đã bị ép buộc thành một số nguyên bởi các phép toán.

Cảm ơn Danko Durbic đã chỉ ra rằng tôi chỉ có thể đảo ngược hoạt động nhân, và không phải chuyển read-hostsang int kể từ khi PowerShell dựa vào các hoạt động của nó trên đối tượng đầu tiên.

Mẹo của PowerShell Golfer: Đối với một số tình huống, như kịch bản này, switchnhịp đập if/else. Ở đây, sự khác biệt là 2 ký tự.

Protip lịch sự của Danko Durbic : Đối với kịch bản cụ thể này, một mảng có thể được sử dụng thay vì switch, để lưu thêm 8 ký tự!

Không có lỗi kiểm tra các giá trị không nguyên hoặc số nguyên nhỏ hơn hai.

Nếu bạn muốn kiểm tra tập lệnh, hãy đặt ;$ingay trước dấu ngoặc cuối cùng trong tập lệnh.

Tôi không chắc chắn chính xác PowerShell xử lý các con số tiến triển thành các giá trị rất lớn như thế nào, nhưng tôi hy vọng độ chính xác sẽ bị mất ở một số điểm. Thật không may, tôi cũng hy vọng sẽ không có nhiều điều có thể được thực hiện về điều đó mà không làm phình to kịch bản.


Mã Ungolfed, với ý kiến:

# Start for loop to run Collatz algorithm.
# Store user input in $i.
# Run until $i reaches 1.
# Increment a counter, $x, with each run.
for($i=(read-host);$i-ne1;$x++)
{
    # New $i is defined based on an array element derived from old $i.
    $i=(
        # Array element 0 is the even numbers operation.
        ($i/2),
        # Array element 1 is the odd numbers operation.
        (3*$i+1)
    # Array element that defines the new $i is selected by $i%2.
    )[$i%2]
}

# Output $x when the loop is done.
$x

# Variable cleanup. Don't include in golfed code.
rv x,i

Các trường hợp thử nghiệm:

Dưới đây là một số mẫu với kiểm toán kích hoạt. Tôi cũng đã chỉnh sửa một số đầu ra cho rõ ràng, bằng cách thêm nhãn vào đầu vào và số cuối cùng và đặt khoảng cách để phân tách các giá trị Collatz.

---
Input: 2

1

Steps: 1

---
Input: 16

8
4
2
1

Steps: 4

---
Input: 5

16
8
4
2
1

Steps: 5

---
Input: 7

22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
1

Steps: 16

---
Input: 42

21
64
32
16
8
4
2
1

Steps: 8

---
Input: 14

7
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
1

Steps: 17

---
Input: 197

592
296
148
74
37
112
56
28
14
7
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
1

Steps: 26

---
Input: 31

94
47
142
71
214
107
322
161
484
242
121
364
182
91
274
137
412
206
103
310
155
466
233
700
350
175
526
263
790
395
1186
593
1780
890
445
1336
668
334
167
502
251
754
377
1132
566
283
850
425
1276
638
319
958
479
1438
719
2158
1079
3238
1619
4858
2429
7288
3644
1822
911
2734
1367
4102
2051
6154
3077
9232
4616
2308
1154
577
1732
866
433
1300
650
325
976
488
244
122
61
184
92
46
23
70
35
106
53
160
80
40
20
10
5
16
8
4
2
1

Steps: 106

---
Input: 6174

3087
9262
4631
13894
6947
20842
10421
31264
15632
7816
3908
1954
977
2932
1466
733
2200
1100
550
275
826
413
1240
620
310
155
466
233
700
350
175
526
263
790
395
1186
593
1780
890
445
1336
668
334
167
502
251
754
377
1132
566
283
850
425
1276
638
319
958
479
1438
719
2158
1079
3238
1619
4858
2429
7288
3644
1822
911
2734
1367
4102
2051
6154
3077
9232
4616
2308
1154
577
1732
866
433
1300
650
325
976
488
244
122
61
184
92
46
23
70
35
106
53
160
80
40
20
10
5
16
8
4
2
1

Steps: 111

---
Input: 8008135

24024406
12012203
36036610
18018305
54054916
27027458
13513729
40541188
20270594
10135297
30405892
15202946
7601473
22804420
11402210
5701105
17103316
8551658
4275829
12827488
6413744
3206872
1603436
801718
400859
1202578
601289
1803868
901934
450967
1352902
676451
2029354
1014677
3044032
1522016
761008
380504
190252
95126
47563
142690
71345
214036
107018
53509
160528
80264
40132
20066
10033
30100
15050
7525
22576
11288
5644
2822
1411
4234
2117
6352
3176
1588
794
397
1192
596
298
149
448
224
112
56
28
14
7
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
1

Steps: 93
---

Các bit thú vị về các số đầu vào không phải từ các trường hợp kiểm tra của câu hỏi:


2
Đẹp! Bạn vẫn có thể rút ngắn phần nào bằng cách thay thế switchbằng$i=(($i/2),($i*3+1))[$i%2]
Danko Durbić

2
Ngoài ra, bạn không phải chuyển đổi read-hostsang số - chỉ cần thay đổi $i*3thành 3*$i.
Danko Durbić

Một mảng thay vì chuyển đổi? Xuất sắc! Và hoán đổi $i*3xung quanh - tại sao tôi chưa nghĩ đến điều đó?
Iszi

1
param($i)for(;$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x- trao đổi máy chủ đọc cho một tham số, để có 56 byte . Liên kết dùng thử trực tuyến
TessellatingHeckler

6

Lắp ráp 80386, 16 byte

Ví dụ này sử dụng cú pháp AT & T và quy ước gọi fastcall, đối số đi vào ecx:

collatz:
        or $-1,%eax              # 3 bytes, eax = -1;
.Loop:  inc %eax                 # 1 byte,  eax += 1;
        lea 1(%ecx,%ecx,2),%edx  # 4 bytes, edx = 3*ecx + 1;
        shr %ecx                 # 2 bytes, CF = ecx & 1;
                                 #          ecx /= 2;
                                 #          ZF = ecx == 0;
        cmovc %edx,%ecx          # 3 bytes, if (CF) ecx = edx;
        jnz .Loop                # 2 bytes, if (!ZF) goto .Loop;
        ret                      # 1 byte,  return (eax);

Dưới đây là 16 byte mã máy kết quả:

83 c8 ff 40 8d 54 49 01 d1 e9 0f 42 ca 75 f4 c3

6

Brachylog , 16 byte

1b|{/₂ℕ|×₃+₁}↰+₁

Hãy thử trực tuyến!

Giải trình

         Either:
  1        The input is 1.
  b        In which case we unify the output with 0 by beheading the 1
           (which removes the leading digit of the 1, and an "empty integer"
           is the same as zero).
|        Or:
  {        This inline predicate evaluates a single Collatz step on the input.
           Either:
    /₂       Divide the input by 2.
    ℕ        And ensure that the result is a natural number (which is
             equivalent to asserting that the input was even).
  |        Or:
    ×₃+₁     Multiply the input by 3 and add 1.
  }
  ↰        Recursively call the predicate on this result.
  +₁       And add one to the output of the recursive call.

Một giải pháp thay thế ở cùng số byte:

;.{/₂ℕ|×₃+₁}ⁱ⁾1∧

Hãy thử trực tuyến!

;.          The output of this is a pair [X,I] where X is the input and
            I will be unified with the output.
{/₂ℕ|×₃+₁}  This is the Collatz step predicate we've also used above.
ⁱ⁾          We iterate this predicate I times on X. Since we haven't actually
            specified I, it is still a free variable that Brachylog can backtrack
            over and it will keep adding on iterations until the next
            constraint can be satisfied.
1           Require the result of the iteration to be 1. Once this is
            satisfied, the output variable will have been unified with
            the minimum number of iterations to get here.
∧           This AND is just used to prevent the 1 from being implicitly
            unified with the output variable as well.


5

F # - 65 ký tự

let rec c n=function 1->n|i->c(n+1)(if i%2=0 then i/2 else i*3+1)

5

Python 68 58 54 52 ký tự

f=lambda n:1+(n-2and f((n/2,3*n+1)[n%2]));f(input())

Cảm ơn Bakuriu và boothby cho những lời khuyên :)


Bạn có thể sử dụng n%2and 3*n+1or n/2để lưu 5 ký tự. Ngoài ra trong python2, bạn có thể loại bỏ cuộc gọi đến int, giảm kích thước xuống 58 byte.
Bakuriu

Ồ, bạn thậm chí có thể nhận được ngắn hơn thế : [n/2,3*n+1][n%2].
gian hàng

Đó là tiện lợi!
CLIN Valentin ngày

Đây có phải là con trăn 2.7? Tôi gặp lỗi trong Python 3.5.1? unsupported operand type(s) for -: 'str' and 'int'
george

5

Võng mạc , 43 byte

11
2
(2+)1
$1$1$0$0$0$0
2.*
$0x
)`2
1
1?x
1

Đưa đầu vào và in đầu ra trong unary.

Mỗi dòng nên đi đến tập tin riêng của mình. 1 byte cho mỗi tệp bổ sung được thêm vào số byte.

Bạn có thể chạy mã dưới dạng một tệp với -scờ. Ví dụ:

> echo -n 1111111|retina -s collatz
1111111111111111

Thuật toán là một vòng lặp thực hiện bước Collatz với số đơn nguyên và thêm một điểm đánh dấu bước mới xở cuối chuỗi nếu số đó không phải là 1.

Khi vòng lặp kết thúc 1, chúng tôi chuyển đổi các điểm đánh dấu thành một số đơn nguyên (loại bỏ hàng đầu 1) là đầu ra mong muốn.


5

Thạch , không cạnh tranh

12 byte Câu trả lời này không cạnh tranh, vì thử thách trước khi tạo ra Jelly.

×3‘$HḂ?ß0’?‘

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

×3‘$HḂ?ß0’?‘  Main link. Argument: n (integer)

     Ḃ?       Yield the last bit of n is 1:
   $            Evaluate the three links to the left as a monadic chain:
×3                Multiply n by 3.
  ‘               Increment the product by 1.
    H           Else, halve n.
         ’?   If n-1 is non-zero:
       ß        Recursively call the main link.
        0     Else, yield 0.
           ‘  Increment the result by 1.

4

dc, 27 ký tự

Áp dụng ma thuật đen của boothby :

?[d3*1+d2%5*1+/d1<x]dsxxkzp

Tôi không thực sự chắc chắn nếu tôi hiểu làm thế nào - hoặc điều đó - nó hoạt động.

Sử dụng:
$ dc collatz.dc <<< 7
16

dc, 36 ký tự

Sáng tạo của riêng tôi; một cách tiếp cận truyền thống hơn, thậm chí tho tôi phải vật lộn với ngôn ngữ một chút công bằng để khắc phục việc thiếu một elsephần để ifphát biểu:

?[2/2Q]se[dd2%[0=e3*1+]xd1<x]dsxxkzp

Trong nội bộ, nó tạo ra tất cả các số của chuỗi và lưu trữ chúng trên ngăn xếp, sau đó bật cuối cùng 1và hiển thị chiều cao của ngăn xếp.


1
Chẵn lẻ không phải là ma thuật đen.
gian hàng

1
Không, nhưng đó là một mẹo rất gọn gàng ở đó! Tôi thực sự đã làm những thứ tương tự bản thân mình, tôi chỉ không nghĩ về nó trong trường hợp này. Điều khiến tôi vấp ngã trong một giây là phép chia, nhưng tôi hiểu được: Bạn chia cho sáu, hoàn nguyên thao tác đầu tiên (* = 3, + = 1) với lần thứ hai nếu tính chẵn lẻ và vì phép chia số nguyên đi đi quá xa, và về cơ bản chúng ta đã hoàn thành / = 2. Rất thông minh :)
daniero

1
+1. Tôi nghĩ rằng tôi sẽ phá vỡ thử thách này với dc, nhưng chỉ đến 40. Tôi đã thấy 27 câu trả lời của bạn. Ồ tốt
Chấn thương kỹ thuật số

Tôi đã không thấy thử thách này, nhưng đã viết lại một lúc về việc in chuỗi Collatz bằng dc. Cách tiếp cận của tôi tương tự như của bạn nhưng mất một byte vì vậy tôi thực sự không thấy lý do để đăng nó. Tuy nhiên, khi tôi đang nhìn vào tôi để xem làm thế nào để dễ dàng chuyển từ in từng bước sang in số bước, tôi phát hiện ra thứ gì đó có thể đánh một byte từ bạn ... Vì chuỗi Collatz sẽ luôn đi từ 2 đến 1, bạn có thể thay đổi điều kiện của bạn để 2<xvà thoát khỏi k. Chỉ trong trường hợp bạn muốn một byte trở lại sau bốn năm. : D
brhfl

4

Brainfuck , 59 56 byte

,-[<->[[>]+<[-<]>>]>[-<<[++>+<]>->]<<[+>+++<]<<+>>>]<<<.

Hãy thử trực tuyến! (Sửa đổi một chút để dễ sử dụng)

Nhập và xuất dưới dạng mã ký tự. Điều này hữu ích hơn với các ô có kích thước tùy ý, nhưng vẫn có thể hoạt động với các giá trị nhỏ trong kích thước ô hạn chế.

Làm thế nào nó hoạt động

Tape Format:
Counter 0 Copy Number Binary...
^End           ^Start

,-[ Get input, decrement by 1 and start loop
  <->                  Initialises the copy of the value at -1
  [[>]+<[-<]>>]        Converts the input to binary while preserving a negative copy
  <+>>[-<<[++>+<]>->] If the last digit of the binary is 1 (n-1 is odd), divide by 2 and decrement
  <<[+>+++<]            If the last digit of the binary is 0 (n-1 is even), multiply by 3
  <<+>>>               Increment counter and end on n-1
]<<<.                 End loop and print counter

4

Lục giác , 48 44 byte

?(]$_)"){{?{*')}/&!/={:<$["/>&_(.<@2'%<>./>=

Hãy thử trực tuyến!

Mở rộng:

     ? ( ] $ _
    ) " ) { { ?
   { * ' ) } / &
  ! / = . { < $ [
 " / > & _ ( . < @
  2 ' % < > : / >
   = . . . . . .
    . . . . . .
     . . . . .

Lưu ý rằng điều này không thành công 1vì ... lý do . Thành thật mà nói, tôi không thực sự chắc chắn làm thế nào điều này hoạt động nữa. Tất cả những gì tôi biết là mã cho số lẻ được chạy ngược cho số chẵn? Bằng cách nào đó?

Phiên bản mới sạch hơn nhiều so với phiên bản trước, nhưng có một vài hướng so sánh hơn và cũng kết thúc bằng lỗi chia cho 0. Trường hợp duy nhất nó không có lỗi là khi nó thực sự xử lý 1chính xác.


If a number < 2 is input ... output does not matter.: o)
Sok

@Sok Yep, đó là lý do tại sao tôi đăng nó thay vì phát điên khi cố gắng khắc phục điều đó
Jo King

3

C, 70 69 ký tự

Khá đơn giản, không có thủ đoạn.
Đọc đầu vào từ stdin.

a;
main(b){
    for(scanf("%d",&b);b-1;b=b%2?b*3+1:b/2)a++;
    printf("%d",a);
}


3

Ruby 1.9, 49 ký tự

Câu trả lời Python của Rubyfied Valentin CLMENT , sử dụng cú pháp lambda mạnh mẽ. Sqeeened nó thành một tuyên bố cho thêm không thể đọc được.

(f=->n{n>1&&1+f[[n/2,3*n+1][n%2]]||0})[gets.to_i]

Một số chi phí vì Ruby, không giống như Python, không hài lòng về việc trộn số với booleans.


3

C ++ ( 51 48)

Đây là một hàm đệ quy thực hiện điều này; đầu vào đọc riêng.

int c(n){return n==1?0:1+(n%2?c(n*3+1):c(n/2));}

Tôi chắc chắn rằng tôi có thể thực hiện một số mẹo "và / hoặc" với == 0công cụ này, nhưng tôi không biết làm thế nào.


Bạn có thể loại bỏ ==0và hoán đổi các mặt của điều kiện
Doorknob

Ngoài ra, không cần xử lý n==1vì tôi đã chỉ định trong câu hỏi rằng số này luôn lớn hơn 1
Doorknob

Vấn đề là n==1trường hợp đệ quy cơ sở. Đặt n==2ở đó sẽ không cải thiện điểm số bất kỳ.
Joe Z.

À, sau đó bạn chỉ có thể thay thế nó bằng cái này: return~-n?và trao đổi các mặt có điều kiện
Doorknob

. n==1== n<2.
Máy

3

~ - ~! (Không có bình luận) - 71 53

Ngôn ngữ này rõ ràng không phải là tốt nhất để chơi golf vì nó thiếu một lượng lớn chức năng bản địa, nhưng đó là vẻ đẹp của nó.

'=|*;~~[*,~~~-~]*/~~|:''=|'''==~[*]'''='&''':''&*+~|:

Đầu tiên, đặt thành '''đầu vào của bạn. Hàm ''sau đó có thể được gọi với %đầu vào và sẽ trả về câu trả lời, như vậy:

'''=~~~~~:''&%:

Điều này sẽ trở lại ~~~~~. Nó thực sự hoạt động cho n==1(nó lặp mãi mãi với n==0).

Như mọi khi với ngôn ngữ này, chưa được kiểm tra.


3

JavaScript (ES6) - 29 ký tự

f=x=>x>1?f(x%2?x*3+1:x/2)+1:0

Tạo một hàm fchấp nhận một đối số duy nhất và trả về số lần lặp.

JavaScript - 31 ký tự

for(c=0;n>1;n=n%2?n*3+1:n/2)++c

Giả sử rằng đầu vào nằm trong biến nvà tạo một biến cchứa số lần lặp (và cũng sẽ xuất ra cbàn điều khiển như là lệnh cuối cùng của nó).



3

Perl 6, 40 byte

Phương pháp hàm đệ quy, theo CLIN Valentindaniero : 40 ký tự

sub f(\n){n>1&&1+f n%2??3*n+1!!n/2}(get)

Phương pháp danh sách lười biếng: 32 ký tự

+(get,{$_%2??$_*3+1!!$_/2}...^1)

3

> <>, 27 26 23 byte

\ln;
\::2%:@5*1+2,*+:2=?

Giống như các câu trả lời khác> <>, điều này xây dựng chuỗi trên ngăn xếp. Khi chuỗi đạt 2, kích thước của ngăn xếp là số bước được thực hiện.

Nhờ @Hohmannfan, đã lưu 3 byte bằng một phương pháp rất thông minh để tính trực tiếp giá trị tiếp theo. Công thức được sử dụng để tính giá trị tiếp theo trong chuỗi là:

f(n)=n5(nmod2)+12+(nmod2)

Phân số ánh xạ các số chẵn thành 0,5 và các số lẻ thành 3. Nhân với nvà thêm n%2hoàn thành phép tính - không cần phải chọn giá trị tiếp theo!

Chỉnh sửa 2: Đây là phiên bản trước- @ Hohmannfan:

\ln;
\:::3*1+@2,@2%?$~:2=?

Thủ thuật ở đây là cả hai 3n+1n/2được tính toán ở mỗi bước trong chuỗi và bước được loại bỏ khỏi chuỗi được chọn sau đó. Điều này có nghĩa là mã không cần phải phân nhánh cho đến khi đạt được 1 và việc tính toán chuỗi có thể nằm trên một dòng mã.

Chỉnh sửa: Bỏ qua một ký tự khác sau khi nhận ra rằng số nguyên dương duy nhất có thể dẫn đến 1 là 2. Vì đầu ra của chương trình không quan trọng đối với đầu vào <2, việc tạo chuỗi có thể kết thúc khi đạt 2, để lại kích thước ngăn xếp là số bước chính xác cần thiết.

Phiên bản trước:

\~ln;
\:::3*1+@2,@2%?$~:1=?

1
Bạn có thể đánh gôn tới 23 nếu bạn mở rộng dòng thứ hai hơn nữa:\::2%:@5*1+2,*+:2=?
Hohmannfan
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.