การคาดคะเน Collatz (OEIS A006577)


66

นี่คือการคาดคะเน Collatz (OEIS A006577 ):

  • เริ่มต้นด้วยจำนวนเต็มn > 1
  • ทำซ้ำขั้นตอนต่อไปนี้:
    • ถ้าnเป็นเลขคู่ให้หารด้วย 2
    • ถ้าnเป็นเลขคี่ให้คูณด้วย 3 แล้วบวก 1

มันได้รับการพิสูจน์ว่าสำหรับจำนวนเต็มบวกทั้งหมดถึง5 * 2 60หรือประมาณ5764000000000000000 , nที่สุดจะกลายเป็น1

งานของคุณคือการหาวิธีการหลายซ้ำก็จะใช้เวลา (จากลดลงครึ่งหนึ่งหรือสามบวกหนึ่ง) ถึง1

xkcd ที่เกี่ยวข้อง :)

กฎ:

  • รหัสที่สั้นที่สุดชนะ
  • หากตัวเลข <2 เป็นอินพุตหรือไม่ใช่จำนวนเต็มหรือไม่ใช่ตัวเลขเอาต์พุตจะไม่สำคัญ

กรณีทดสอบ

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

คำตอบ:


19

GolfScript, 24 23 21 20 18 ตัวอักษร

~{(}{3*).2%6\?/}/,

ถือว่าอินพุตบน stdin ทดสอบออนไลน์


3
1+)เป็นพิเศษใส่ซองเป็น
Peter Taylor

@PeterTaylor แน่นอนลืมไปว่า;)
ความผันผวน

1
เยี่ยมมาก! <! - padding ->
Peter Taylor

1
@Peter: The <! - -> ไม่ทำงานในความคิดเห็น ใช้สิ่งนี้แทน
Ilmari Karonen


15

C - 50 47 ตัวอักษร

น่าเสียดายที่ C เล็ก ๆ น้อย ๆ แต่น่าเสียดายที่ต้องมีรหัสจำนวนมากสำหรับ I / O พื้นฐานดังนั้นการย่อทุกอย่างที่ลงจึงทำให้ UI ไม่ได้ใช้งานง่าย

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

gcc -o 1 collatz.cรวบรวมไว้ด้วยตัวอย่างเช่น การป้อนข้อมูลนั้นไม่พร้อมกันกับตัวเลขที่คั่นด้วยช่องว่างและคุณจะพบคำตอบในรหัสออก ตัวอย่างที่มีหมายเลข 17:

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

1
return~-a?ช่วยประหยัด 1. นอกจากนี้ยังมีการเคลื่อนย้ายb++ไปยังกรณีควรบันทึก? b--
ugoren

อิอิคุณกำลังดัดกฎดังนั้นมาก: P +1 สำหรับความคิดสร้างสรรค์และการใช้ภาษาที่ไม่ได้มักจะใช้ในการกอล์ฟ
Doorknob

ขอบคุณ ugoren! ฉันต้องเมาเมื่อเขียน :)
Fors

12

Perl 34 (+1) ตัวอักษร

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

การละเมิด$\สำหรับผลลัพธ์สุดท้ายตามปกติ เรียกใช้กับตัวเลือกบรรทัดคำสั่งเข้ามาจาก-pstdin

ที่บันทึกไว้หนึ่งไบต์เนื่องจากอีเลียสแวน Ootegem โดยเฉพาะการสังเกตว่าทั้งสองต่อไปนี้เทียบเท่า:

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

แม้ว่าหนึ่งไบต์อีกต่อไปมันจะช่วยประหยัดไบต์ที่สองโดยการตัดทอนให้เหลือเพียง$_/2.5

ตัวอย่างการใช้งาน:

$ echo 176 | perl -p collatz.pl
18

PHP 54 ไบต์

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

จาวาสคริปต์สำหรับรางวัล Wooden Spoon Award ดูเหมือนจะสั้นลงเล็กน้อยในความท้าทายนี้ แม้ว่าจะมีพื้นที่ไม่มากนักสำหรับการสร้างสรรค์ด้วยปัญหานี้ อินพุตถูกใช้เป็นอาร์กิวเมนต์บรรทัดคำสั่ง

ตัวอย่างการใช้งาน:

$ php collatz.php 176
18

1
เอาฉันในขณะที่จะคิดออกว่าสิ่งที่ไม่มีใครเทียบวงเล็บกำลังทำ :)
marinus

1
การทำซ้ำ$_ใน ternary ดูเหมือนสิ้นเปลืองคุณสามารถโกนตัวละครอื่นโดยใช้เช่นนี้*= $\++,$_*=$_&1?3+1/$_:.5while$_>1}{การคูณโดย1/$_มีผลเช่นเดียวกัน+1ดังนั้นจึง$_*=3+1/$_ใช้ได้ดี
Elias Van Ootegem

@EliasVanOotegem $_*=3+1/$_ยอดเยี่ยมมากขอบคุณ!
โม่

11

Mathematica (35)

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

การใช้งาน:

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

มันไม่ใช่ฟังก์ชั่นที่ถูกต้อง 10.3 บ่นเกี่ยวกับการโกง @ ในตอนท้าย
CalculatorFeline

@ จะเรียกโต้แย้งผมไม่ทราบว่าทำไมมันอยู่ที่นั่นเป็นเพียงแค่การแก้ไขอย่างรวดเร็ว
ไมล์

ต้องระวัง :)
CalculatorFeline

10

ตามปกติฉันจะเริ่มคำตอบด้วยตัวเอง

JavaScript, 46 44 ตัวอักษร (ทำงานบนคอนโซล)

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

อะไรคือจุดของ ~~ prompt () ถ้าคุณพูดว่า output ไม่สำคัญว่ามันจะไม่ใช่จำนวนเต็ม? คุณสามารถบันทึกอักขระสองตัวโดยกำจัด ~~
Resorath

@Resorath Ah ลืมการหล่ออัตโนมัติของ JS: P ขอบคุณ
Doorknob

9

ชวา, 165, 156, 154,134,131,129,128 , 126 (ภาษา verbose ต้องการความรักเช่นกัน)

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));}}

ทุกอย่างเสร็จสิ้นภายในสำหรับ

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

นั่นเป็นผู้ชายที่สวยงาม ขอบคุณ Pater Taylor !!! และแนวคิดของการใช้ลูป for ถูกขโมยจาก ugoren

ฉันเปลี่ยน Integer เป็น Short


1
i(,++y)คุณสามารถค่อนข้างง่ายและบันทึกความยาวของ คุณสามารถบันทึกทั้งสองมากขึ้นโดยใช้แทน< ==
Peter Taylor

@PeterTaylor คุณถูกต้องการเปรียบเทียบของฉันจะสั้นลงด้วย <แต่ฉันไม่เข้าใจในส่วนของการเพิ่มขึ้นก่อน
jsedano

2
ทั้งสองด้านของ ternary ที่สองของคุณมีโครงสร้างที่เหมือนกันดังนั้นคุณสามารถส่ง ternary ไปยังอาร์กิวเมนต์แรกของการเรียกแบบเรียกซ้ำ
Peter Taylor

1
โอ้พระเจ้าของฉันนั่นเป็นความ
สดใส

2
ฉันรู้ว่ามันได้รับประมาณ 3.5 ปี แต่คุณยังสามารถเล่นกอล์ฟได้โดยไบต์ 5 : 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;}}การเปลี่ยนแปลงที่ทำ: 1) แทนที่Short.valueOf(...)ด้วยnew Short(...)สำหรับ-4 ไบต์และ 2) ผมเคยใส่x=x%2<1?x/2:x*3+1;ในร่างกายของfor-loop การกำจัดของ จุลภาคสำหรับ-1 ไบต์
Kevin Cruijssen

9

Rebmu : 28

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

สำหรับปัญหาสั้น ๆ และคณิตศาสตร์นี้ GolfScript มีแนวโน้มที่จะชนะโดย Rebmu ร้อยละ (ถ้าไม่จำเป็นต้องพูดให้อ่านไฟล์จากอินเทอร์เน็ตหรือสร้างไฟล์ JPG) แต่ฉันคิดว่าส่วนใหญ่จะเห็นด้วยกับตรรกะของ Golfscript นั้นใกล้ที่จะติดตามได้ง่ายและกองปฏิบัติการที่รันได้ทั้งหมดนั้นใหญ่กว่า

แม้ว่า REBOL ของผู้สร้างเองคาร์ล Sassenrathบอกผมว่าเขาพบ Rebmu "อ่านไม่ได้" เขาไม่ว่างและไม่ได้มีเวลาที่จะปฏิบัติจริงการเปลี่ยนแปลงหมูละตินเหมือนผ่านunmushing นี่เป็นเพียงการแปลง:

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

โปรดทราบว่าพื้นที่ที่ถูกต้องที่จะได้รับ: การแทน นี่คือ "ชุดคำ!" และผู้ประเมินจะสังเกตเห็นว่าสัญลักษณ์ประเภทใดที่จะทริกเกอร์การมอบหมาย

หากมีการเขียนในตัวย่อ (ยังเขียน Rebol อย่างเชื่องช้า) คุณจะได้รับ:

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

Rebol เช่น Ruby จะประเมินบล็อกเป็นค่าสุดท้าย UNTIL loop เป็นรูปแบบของการวนรอบที่แปลกประหลาดที่ไม่มีเงื่อนไขการวนซ้ำมันจะหยุดการวนซ้ำเมื่อบล็อกของมันประเมินสิ่งที่ไม่ใช่ FALSE หรือ NONE ดังนั้น ณ จุดที่1 ==ผลลัพธ์ของการกำหนด A (อาร์กิวเมนต์ให้ rebmu) ให้กับผลลัพธ์ของ Collatz เงื่อนไข (เช่น IF-ELSE ซึ่งประเมินให้กับสาขาที่เลือก) ... การแบ่งลูป

J และ K ถูกเตรียมใช้งานเป็นค่าจำนวนเต็มศูนย์ใน Rebmu และดังที่กล่าวไปแล้วสิ่งทั้งปวงจะประเมินเป็นค่าสุดท้าย ดังนั้นการอ้างอิง J ในตอนท้ายของโปรแกรมหมายความว่าคุณจะได้จำนวนการทำซ้ำ

การใช้งาน:

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

8

Python ทำสำเนา 48

n=3*n+1;n/=1+n%2*5;ฉันไม่มั่นใจว่าจะไม่มีการแสดงออกที่สั้นกว่า ฉันอาจพบนิพจน์ที่แตกต่างกันหลายสิบรายการที่มีความยาวเท่ากัน ...

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

แก้ไข: ฉันได้พบวิธีแก้ไขปัญหาอื่นที่จะไม่โต้แย้ง แต่สนุกเกินไปที่จะไม่แบ่งปัน

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
สมองของฉันเจ็บตอนนี้
daniero

1
@daniero ทางออกที่สองนั้นเหมาะสำหรับคุณ
บูธโดย

โอ้ว้าว. ฉันรู้สึกเป็นเกียรติ!
daniero

4
(n//2,n*3+1)[n%2]สั้นกว่า
Evpok

1
@Evpok จะไม่n/2ทำงานเช่นเดียวกับที่เรารู้ว่ามันเป็นยัง?
george

7

APL (31)

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

คำตอบเก่ายัง 27:{1=⍵:0⋄2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}
Uriel

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

7

J, 30 ตัวอักษร

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

กลับกลายเป็นค่อนข้างนานกว่าที่ต้องการ

ใช้:

   <:#-:`(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&*)`]เป็น gerund ประกอบด้วยสามคำกริยาใช้สามครั้ง -:หมายถึง "halve" (1+3&*)หรือ(1+3*])เข้ารหัสขั้นตอนการคูณและ](identity) ช่วยในการยกเลิก

  • 2&|+1&=รูปแบบดัชนีไปยัง gerund ตัวอักษร "ส่วนที่เหลือหลังจากการหารด้วยสองบวกไม่ว่าจะเท่ากับหนึ่ง"

  • #verb^:a:ทำซ้ำฟังก์ชันจนกว่าผลลัพธ์จะมีเสถียรภาพ (ที่นี่บังคับอย่างชัดเจน) ขณะรวบรวมขั้นตอนจากนั้นนับจำนวน ขโมยมาจาก @JB <:ลดจำนวนขั้นตอนทีละหนึ่งเพื่อให้สอดคล้องกับข้อกำหนดของคำถาม


6
เมื่อใดก็ตามที่ฉันเห็นญัตติ J ฉันจะนับรอยยิ้ม คนนี้ไม่สวยดี: <:, #-:, :`(, &*), ,=) )^:
โม่

3
@primo ดี ต้องการคำอธิบายหรือไม่ :-) <:หมายถึง "decrement" หรือ "น้อยกว่าหรือเท่ากับ" #หมายถึง "count of" หรือ "n times" -:หมายถึง "halve" หรือ "epsilon-equality" :`(หมายถึงการสิ้นสุด "halve" ซึ่งหมายถึงการผูกระหว่าง คำกริยาสองคำใน gerund และวงเล็บปีกซ้าย (ใช้สำหรับการจัดกลุ่ม) &*)หมายถึง "sth. ถูกผูกมัดกับการคูณ" (3 ถูกผูกมัดด้วยการคูณสร้างตัวดำเนินการ "คูณสาม") และจุดสิ้นสุดของการจัดกลุ่ม =ดำเนินการตรวจสอบความเสมอภาคหรือในแง่ที่เป็นเอกเทศการจำแนกตนเอง ^:คือการรวมพลัง (การทำซ้ำกริยา) เนื่องจากคำกริยา J จำนวนมากลงท้ายด้วยโคลอน ... :-)
John Dvorak

หลายปีต่อมา ... บล็อกลูปที่ปรับปรุงแล้ว: '- & 2 # (> & 1 * -: + 2 & | * +: +>: @ -:) ^: a:' -> -1 ถ่าน : P
randomra

อีกหลายปีต่อมา ... <:#a:2&(<*|+|6&*%~)19 ไบต์ (-11)
ไมล์

6

รูปแบบการเล่นกล106 106ตัวอักษร 40 วงเล็บ

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

91 89 chars ที่กำหนดโดยตรง

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


ฉันไม่ได้อยู่แถวนี้มานาน แต่ฉันสังเกตว่าคนมักจะโพสต์ 1 คำตอบต่อการเขียนโปรแกรมภาษา
jsedano

ขออภัยฉันไม่ทราบ :) :)
Valentin CLEMENT

แก้ไขเพื่อลบ Python อย่างใดอย่างหนึ่ง
Valentin CLEMENT

1
ไม่จริง! คนมักจะโพสต์หนึ่งคำตอบต่อการเขียนโปรแกรมภาษา แต่นั่นเป็นเพราะพวกเขาพยายามที่จะไม่แข่งขันโดยตรงกับคนอื่นด้วยคำตอบที่สั้นกว่า แต่ไม่มีใครจะบ่นถ้าคุณโพสต์คำตอบที่แตกต่างในภาษาเดียวกัน
breadbox

@ กล่องจดหมายไม่เป็นความจริง ฉันโพสต์หนึ่งคำตอบต่อภาษาหากโซลูชันแต่ละตัวมีความน่าสนใจด้วยตัวเองเมื่อเปรียบเทียบกับภาษาอื่น หากทั้งสองวิธีมีความน่าสนใจเท่า ๆ กันทั้งคู่ (อัลกอริทึมเดียวกันไม่มีลูกเล่นภาษาที่น่าสนใจ) ฉันจะโพสต์พวกเขาเป็นหนึ่งเดียว ปกติฉันจะไม่โพสต์วิธีแก้ปัญหาหลายอย่างเพราะฉันเลือกภาษาก่อนจากนั้นจึงแก้ปัญหาในภาษานั้น - จากนั้นฉันมักจะขี้เกียจเกินกว่าจะเขียนในภาษาอื่น - หรือฉันเริ่มเดินทางเพื่อเรียนรู้การเขียนโปรแกรมอื่น ภาษา.
John Dvorak

6

PowerShell: 77 74 71 70 61

รหัส Golfed:

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

หมายเหตุ:

ตอนแรกฉันพยายามที่จะป้อนข้อมูลผู้ใช้โดยไม่บังคับให้เป็นจำนวนเต็ม อินพุตแปลก ๆ จะประมวลผลไม่ถูกต้อง แต่แม้อินพุตจะทำงานได้ดี ฉันใช้เวลาสักครู่เพื่อตระหนักว่าเกิดอะไรขึ้น

เมื่อทำการคูณหรือการเพิ่ม PowerShell จะถือว่าอินพุตที่ไม่ได้พิมพ์เป็นสตริงก่อน ดังนั้น'5'*3+1กลายเป็น '5551' แทน 16 อินพุตที่เข้ากันได้ดีเนื่องจาก PowerShell ไม่มีการดำเนินการเริ่มต้นสำหรับการหารกับสตริง แม้แต่อินพุตที่มีความคืบหน้าผ่านเลขคี่ก็ใช้ได้ดีเพราะเมื่อ PowerShell ถึงเลขคี่ในลูปตัวแปรก็ถูกบังคับให้เป็นจำนวนเต็มโดยการดำเนินการทางคณิตศาสตร์อยู่แล้ว

ขอบคุณDanko Durbicสำหรับการชี้ให้เห็นฉันสามารถสลับการดำเนินการคูณและไม่ต้องแปลงread-hostเป็น int เนื่องจาก PowerShell ใช้การดำเนินการกับวัตถุแรก

เคล็ดลับ PowerShell นักกอล์ฟ: สำหรับบางสถานการณ์เช่นนี้หนึ่งจังหวะswitch if/elseนี่คือความแตกต่างคือ 2 ตัวอักษร

Protip Courtesy of Danko Durbic : สำหรับสถานการณ์นี้คุณสามารถใช้อาเรย์แทนswitchเพื่อบันทึกอักขระได้อีก 8 ตัว!

ไม่มีข้อผิดพลาดในการตรวจสอบค่าที่ไม่ใช่จำนวนเต็มหรือจำนวนเต็มน้อยกว่าสอง

หากคุณต้องการตรวจสอบสคริปต์ให้ใส่;$iวงเล็บปิดล่าสุดไว้ในสคริปต์

ฉันไม่แน่ใจว่า PowerShell สามารถจัดการกับตัวเลขที่คืบหน้าไปสู่ค่าที่มีขนาดใหญ่มากเพียงใด แต่ฉันคาดว่าความแม่นยำจะหายไปในบางจุด น่าเสียดายที่ฉันยังคาดหวังว่าจะมีไม่มากที่สามารถทำได้เกี่ยวกับสิ่งนั้นโดยไม่ทำให้สคริปต์รุนแรง


รหัส Ungolfed พร้อมความคิดเห็น:

# 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

กรณีทดสอบ:

ด้านล่างคือตัวอย่างบางส่วนที่เปิดใช้งานการตรวจสอบ ฉันยังแก้ไขผลลัพธ์บางอย่างเพื่อความชัดเจนโดยการเพิ่มเลเบลให้กับอินพุตและการนับครั้งสุดท้ายและใส่ระยะห่างเพื่อแยกค่า 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
---

บิตที่น่าสนใจเกี่ยวกับหมายเลขอินพุตที่ไม่ได้มาจากกรณีทดสอบของคำถาม:


2
ดี! คุณยังสามารถย่อให้สั้นลงได้โดยแทนที่switchด้วย$i=(($i/2),($i*3+1))[$i%2]
Danko Durbić

2
นอกจากนี้คุณยังไม่ได้มีการแปลงread-hostไปยังหมายเลข - เพียงแค่เปลี่ยนไป$i*3 3*$i
Danko Durbić

อาร์เรย์แทนสวิตช์? ยอดเยี่ยม! และสลับ$i*3ไปมา - ทำไมฉันไม่คิดอย่างนั้น?
Iszi

1
param($i)for(;$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x- สลับอ่านโฮสต์สำหรับพารามิเตอร์ที่จะได้รับ56 ไบต์ ลองลิงค์ออนไลน์
TessellatingHeckler

6

ชุดประกอบ 80386 ขนาด 16 ไบต์

ตัวอย่างนี้ใช้ไวยากรณ์ของ AT&T และการเรียกประชุม fastcall อาร์กิวเมนต์มี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);

นี่คือรหัสเครื่องที่เกิดขึ้น 16 ไบต์:

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

6

Brachylogขนาด 16 ไบต์

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

ลองออนไลน์!

คำอธิบาย

         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.

โซลูชันทางเลือกที่นับไบต์เดียวกัน:

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

ลองออนไลน์!

;.          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

Python 68 58 54 52 ตัวอักษร

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

ขอบคุณบาคุริและบูธบายสำหรับคำแนะนำ :)


คุณสามารถใช้n%2and 3*n+1or n/2เพื่อบันทึก 5 ตัวอักษร นอกจากนี้ใน python2 คุณสามารถลบการโทรออกได้intโดยลดขนาดเป็น 58 ไบต์
Bakuriu

[n/2,3*n+1][n%2]โอ้คุณยังสามารถได้รับสั้นกว่า:
บูธโดย

นั่นคือดี!
Valentin CLEMENT

หลาม 2.7 นี้หรือไม่ ฉันได้รับข้อผิดพลาดใน Python 3.5.1 หรือไม่ unsupported operand type(s) for -: 'str' and 'int'
george

5

เรติน่า 43 ไบต์

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

ใช้อินพุตและพิมพ์เอาต์พุตใน unary

แต่ละบรรทัดควรไปที่ไฟล์ของตนเอง 1 ไบต์ต่อไฟล์พิเศษที่เพิ่มลงในจำนวนไบต์

คุณสามารถเรียกใช้รหัสเป็นหนึ่งไฟล์ด้วยการ-sตั้งค่าสถานะ เช่น:

> echo -n 1111111|retina -s collatz
1111111111111111

อัลกอริธึมเป็นการวนซ้ำของการทำขั้นตอน Collatz โดยใช้หมายเลขยูนารีและเพิ่มตัวทำเครื่องหมายขั้นตอนใหม่xที่ท้ายสตริงถ้าตัวเลขนั้นไม่ใช่ 1

เมื่อลูปสิ้นสุดลง1เราจะแปลงเครื่องหมายเป็นจำนวนยูนารี (นำส่วนนำออก1) ซึ่งเป็นเอาต์พุตที่ต้องการ


5

เยลลี่ไม่ใช่การแข่งขัน

12 ไบต์ คำตอบนี้ไม่ใช่การแข่งขันเนื่องจากความท้าทายมาก่อนการสร้างเยลลี่

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

ลองออนไลน์!

มันทำงานอย่างไร

×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 ตัวอักษร

การใช้เวทย์มนตร์สีดำของบู๊ทบาย :

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

ฉันไม่แน่ใจจริงๆถ้าฉันเข้าใจว่ามันทำงานอย่างไร

การใช้งาน:
$ dc collatz.dc <<< 7
16

dc, 36 ตัวอักษร

การสร้างของฉันเอง; วิธีการแบบดั้งเดิมค่อนข้างมากถึงแม้ว่าฉันต้องทะเลาะกับภาษาที่ค่อนข้างยุติธรรมเพื่อเอาชนะการขาดelseส่วนของifข้อความ:

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

ภายในผลิตหมายเลขทั้งหมดของลำดับและเก็บไว้ในสแต็คจากนั้นปรากฏขึ้นสุดท้าย1และแสดงความสูงสแต็ค


1
ความเท่าเทียมกันไม่ใช่มนต์ดำ
บูธโดย

1
ไม่ แต่มันเป็นกลอุบายที่ประณีตมาก ๆ ! ฉันทำสิ่งที่คล้ายกันจริง ๆ แล้วฉันไม่ได้คิดถึงมันในกรณีนี้ สิ่งที่ฉันสะดุดเป็นครั้งที่สองคือการหาร แต่ฉันเข้าใจ: คุณหารด้วยหก, การคืนค่าการดำเนินการครั้งแรก (* = 3, + = 1) ด้วยวินาทีถ้าความเท่าเทียมกันผิดและเนื่องจากการหารเต็ม ออกไปด้วยและเราก็ทำโดยทั่วไปแล้ว / = 2 ฉลาดมาก :)
daniero

1
+1 ฉันคิดว่าฉันจะเอาชนะความท้าทายนี้ด้วย dc แต่ทำได้แค่ 40 เท่าฉันเห็นคำตอบของคุณ 27 ข้อ โอ้ดี
Digital Trauma

ฉันไม่เห็นความท้าทายนี้ แต่กลับมาเขียนบทความเกี่ยวกับลำดับ Collatz อีกครั้ง วิธีการของฉันคล้ายกับของคุณ แต่แพ้ไบต์ดังนั้นฉันจึงไม่เห็นเหตุผลในการโพสต์ อย่างไรก็ตามเมื่อฉันมองดูของฉันเพื่อดูวิธีการพิมพ์จากแต่ละขั้นตอนไปจนถึงการพิมพ์จำนวนขั้นตอนฉันพบสิ่งที่สามารถตีไบต์ของคุณได้ ... เนื่องจากลำดับ Collatz จะเปลี่ยนจาก 2 เป็น 1 เสมอ คุณสามารถเปลี่ยนเงื่อนไขของคุณไปและกำจัดของ2<x kในกรณีที่คุณต้องการไบต์กลับหลังจากสี่ปี : D
brhfl

4

brainfuck , 59 56 ไบต์

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

ลองออนไลน์! (ปรับเปลี่ยนเล็กน้อยเพื่อความสะดวกในการใช้งาน)

อินพุตและเอาต์พุตเป็นรหัสอักขระ สิ่งนี้มีประโยชน์มากขึ้นกับเซลล์ที่มีขนาดตามอำเภอใจ แต่ยังสามารถทำงานกับค่าเล็กในขนาดเซลล์ที่ จำกัด ได้

มันทำงานอย่างไร

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

Hexagony , 48 44 ไบต์

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

ลองออนไลน์!

ขยาย:

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

โปรดทราบว่านี้ล้มเหลวบน1สำหรับเอ่อ ... เหตุผล สุจริตฉันไม่แน่ใจจริงๆว่าวิธีนี้ทำงานได้อีกต่อไป สิ่งที่ฉันรู้ก็คือรหัสสำหรับเลขคี่นั้นวิ่งไปข้างหลังเป็นเลขคู่ อย่างใด?

เวอร์ชันใหม่นั้นสะอาดกว่ารุ่นก่อนมาก แต่มีทิศทางเปรียบเทียบน้อยกว่าและจบลงด้วยข้อผิดพลาดหารด้วยศูนย์ กรณีเดียวที่ไม่มีข้อผิดพลาดคือเมื่อมันจัดการ1ได้อย่างถูกต้องจริง


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

@Sok ครับว่าทำไมผมโพสต์มันแทนจะบ้าพยายามที่จะแก้ไขปัญหาที่
โจกษัตริย์

3

C, 70 69 ตัวอักษร

ค่อนข้างง่ายไม่มีเทคนิค
อ่านอินพุตจาก 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 ตัวอักษร

คำตอบ Pythonของ Rubyfied Valentin CLEMENT โดยใช้ไวยากรณ์ stabby lambda บีบมันเป็นคำสั่งเดียวเพื่อเพิ่มความไม่สามารถอ่านได้

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

บางคนค่าใช้จ่ายเพราะทับทิมซึ่งแตกต่างจาก Python ไม่มีความสุขกับการผสมตัวเลขกับบูลีน


3

C ++ ( 51 48)

นี่คือฟังก์ชันแบบเรียกซ้ำที่ทำสิ่งนี้ การอ่านอินพุตแยกต่างหาก

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

ฉันแน่ใจว่าฉันสามารถทำอะไรบางอย่าง "และ / หรือ" หลอกลวงด้วย== 0สิ่งของ แต่ฉันไม่รู้ว่าอย่างไร


คุณสามารถลบ==0และสลับด้านข้างของเงื่อนไข
Doorknob

นอกจากนี้ไม่จำเป็นต้องจัดการn==1เพราะฉันระบุในคำถามว่าจำนวนมากกว่า 1 เสมอ
Doorknob

ปัญหาคือว่าn==1เป็นกรณีการเรียกซ้ำฐาน การวางที่n==2นั่นจะไม่ปรับปรุงคะแนนใด ๆ
Joe Z.

อ่าคุณก็สามารถแทนที่มันด้วยสิ่งนี้return~-n?และสลับข้างตามเงื่อนไข
Doorknob

. ==n==1 n<2
CalculatorFeline

3

~ - ~! (ไม่มีความคิดเห็น) - 71 53

ภาษานี้เห็นได้ชัดว่าไม่ได้ดีที่สุดสำหรับการเล่นกอล์ฟเนื่องจากมันไม่มีฟังก์ชั่นดั้งเดิมมากมาย แต่นั่นคือความงดงามของมัน

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

ก่อนอื่นให้ตั้งค่า'''อินพุตของคุณ ''สามารถเรียกใช้ฟังก์ชั่นพร้อมกับ%อินพุตและจะส่งคืนคำตอบดังนี้:

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

~~~~~นี้จะกลับ ใช้งานได้จริงn==1(มันวนซ้ำไปตลอดกาลn==0)

เช่นเคยกับภาษานี้ยังไม่ได้ทดสอบ


3

JavaScript (ES6) - 29 ตัวอักษร

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

สร้างฟังก์ชั่นfที่ยอมรับการโต้แย้งเดียวและส่งกลับจำนวนของการทำซ้ำ

JavaScript - 31 ตัวอักษร

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

สมมติว่าอินพุตอยู่ในตัวแปรnและสร้างตัวแปรcซึ่งมีจำนวนการวนซ้ำ (และจะส่งออกcไปยังคอนโซลเป็นคำสั่งสุดท้าย)



3

Perl 6, 40 ไบต์

วิธีฟังก์ชั่นแบบเรียกซ้ำตามValentin CLEMENTและdaniero : 40 ตัวอักษร

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

วิธีรายการที่ขี้เกียจ: 32 ตัวอักษร

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

3

> <>, 27 26 23 ไบต์

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

เช่นเดียวกับคำตอบอื่น ๆ > <> สิ่งนี้จะสร้างลำดับบนสแต็ก เมื่อลำดับถึง 2 ขนาดของสแต็กคือจำนวนขั้นตอนที่ใช้

ขอบคุณ @Hohmannfan ช่วยให้ประหยัดได้ 3 ไบต์ด้วยวิธีการคำนวณค่าถัดไปที่ชาญฉลาดมาก สูตรที่ใช้ในการคำนวณค่าถัดไปในลำดับคือ:

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

เศษส่วนจะแมปถึง 0.5 และจำนวนคี่เป็น 3 คูณด้วยnและเพิ่มn%2การคำนวณเสร็จสมบูรณ์ - ไม่จำเป็นต้องเลือกค่าถัดไปเลย!

แก้ไข 2:ต่อไปนี้เป็นรุ่นก่อน @ Hohmannfan:

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

เคล็ดลับที่นี่คือทั้งสอง3n+1และn/2ถูกคำนวณในแต่ละขั้นตอนในลำดับและหนึ่งที่จะลดลงจากลำดับที่เลือกหลังจากนั้น ซึ่งหมายความว่ารหัสไม่จำเป็นต้องแยกสาขาจนกว่าจะถึง 1 และการคำนวณลำดับสามารถมีชีวิตอยู่ในหนึ่งบรรทัดของรหัส

แก้ไข: Golfed off ตัวละครอื่นหลังจากตระหนักว่าจำนวนเต็มบวกเท่านั้นที่สามารถนำไปสู่ ​​1 คือ 2 เนื่องจากผลลัพธ์ของโปรแกรมไม่สำคัญสำหรับอินพุต <2 การสร้างลำดับสามารถสิ้นสุดได้เมื่อถึง 2 โดยเหลือขนาดสแต็ก เป็นจำนวนขั้นตอนที่แน่นอนที่จำเป็น

รุ่นก่อนหน้า:

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

1
คุณสามารถตีมันถึง 23 ถ้าคุณไม่ลบบรรทัดที่สองมากยิ่งขึ้น:\::2%:@5*1+2,*+:2=?
Hohmannfan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.