Collatz Conjecture (OEIS A006577)


66

Це Конлат Коллаца (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+має особливий характер ).
Пітер Тейлор

@PeterTaylor звичайно, забув про це;)
Нестабільність

1
Хороша робота! <! - padding ->
Пітер Тейлор

1
@Peter: <! - -> не працює в коментарях. Використовуйте це замість цього.
Ільмарі Каронен


15

C - 50 47 символів

Бідний маленький C, на жаль, вимагає жахливої ​​кількості коду для базового вводу-виводу, тому скорочення всього, що знижується, зробило інтерфейс користувача трохи неінтуїтивним.

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

Дякую угорен! Я, мабуть, був п’яний, коли писав це. :)
Fors

12

Perl 34 (+1) символів

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

Зловживання $\для остаточного виходу, як зазвичай. Запуск з -pпараметром командного рядка, введення береться з stdin.

Збережено один байт завдяки Elias Van 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;

Архіменез Javascript для нагороди «Дерев’яна ложка», схоже, трохи не впорався з цим завданням. Однак, не дуже багато місця для творчості з цією проблемою. Введення приймається як аргумент командного рядка.

Використання зразка:

$ php collatz.php 176
18

1
Зайняв мене час, щоб зрозуміти, що роблять незрівнянні дужки :)
marinus

1
Повторюючи $_в троичной здається марнотратним, ви можете збрити іншого персонажа, використовуючи *=так: $\++,$_*=$_&1?3+1/$_:.5while$_>1}{. Перемноження на 1/$_той же ефект, що і +1, тому $_*=3+1/$_працює чудово
Еліас Ван Оотегем,

@EliasVanOotegem $_*=3+1/$_геніальний, дякую!
примо

11

Математика (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

@ викликає аргумент, я не знаю, чому це було там, просто швидка редагування
милі

Треба бути обережним :)
КалькуляторFeline

10

Як я зазвичай це роблю, я почну відповіді своїми власними.

JavaScript, 46 44 символів (працює на консолі)

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

Який сенс у ~~ prompt (), якщо ви сказали, що вихід не має значення, чи це неціле число? Ви можете зберегти два символи, позбувшись ~~.
Resorath

@Resorath Ах, забув про автоматичний кастинг JS: P спасибі
Doorknob

9

Java, 165, 156, 154,134,131,129,128 , 126 (багатослівні мови теж потребують любові)

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

Це вигадливий прекрасний чоловік. Спасибі Патеру Тейлору !!!, а ідея використання петлі була вкрадена у ugoren

Я замінив Integer на Short.


1
Ви можете досить легко зберегти довжину i(,++y). Можна зберегти ще два, використовуючи <замість ==.
Пітер Тейлор

@PeterTaylor Ви праві, мої порівняння будуть коротшими з <, але я не розумію частину попереднього приросту
jsedano

2
Дві сторони вашого другого тернара структурно однакові, тому ви можете підштовхнути тернар до першого аргументу рекурсивного виклику.
Пітер Тейлор

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

Ребму : 28

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

Проблема, яка ця стисла і непомітна, GolfScript, швидше за все, виграє на кілька відсотків проти Rebmu (якщо цього не потрібно говорити, читайте файли з Інтернету або генеруйте файли JPG). Але я думаю, що більшість погодиться з логікою Golfscript ніде не так легко дотримуватися, і загальний виконуваний стек, який працює на ньому, більший.

Хоча власний творець Ребола Карл Сассенрат сказав мені, що він вважає Ребму "нечитабельною", він зайнятий, і не встиг реально практикувати свино-латиноподібну трансформацію шляхом розбиття . Це справді просто перетворюється на:

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

Зауважте, що для отримання знаку " a" замість " a" потрібно було пробілу . Це "набір слово!" і оцінювач помічає цей тип символу для запуску призначення.

Якби це було написано у необмеженому вигляді (але незручно написане Rebol), ви отримаєте:

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

Rebol, як і Ruby, оцінює блоки за останнім значенням. Цикл UNTIL - це допитлива форма циклу, яка не приймає умови циклу, вона просто припиняє циклічно, коли його блок оцінює щось не FALSE або NONE. Тож у тому випадку, 1 ==коли результат присвоєння A (аргументу ребму) результату Collatz умовно (або IF-ELSE, який оцінює вибрану ним гілку) ... цикл розривається.

J і K ініціалізуються до цілого значення нуля в Rebmu. І як було сказано вище, вся справа оцінюється до останнього значення. Отже, посилання на J в кінці програми означає, що ви отримаєте кількість ітерацій.

Використання:

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

8

Python repl, 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]коротше.
Євпок

1
@Evpok не n/2працюватиме так добре, як ми знаємо, що це навіть?
Джордж

7

APL (31)

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

стара відповідь, все ж, 27:{1=⍵:0⋄2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}
Уріель

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&*)`]- це герундія, складена з трьох дієслів, вживана в три рази. -:означає "наполовину" (1+3&*)або (1+3*])кодує етап множення і ](ідентичність) сприяє припиненню.

  • 2&|+1&=утворює індекс до герунди. буквально, "залишок після ділення на два плюс, будь то рівний одному".

  • #verb^:a:ітератує функцію, поки результат не буде стабільним (тут, вимушено явно), збираючи кроки, потім підраховує їх. Викрадено у @JB . <:декременти підраховують крок на одиницю, щоб відповідати вимогам запитання.


6
Щоразу, коли я бачу подання на J, я рахую посмішки. Це один робить досить добре: <:, #-:, :`(, &*), =), )^:.
примо

3
@primo приємно; хочете їх пояснення? :-) <:означає "декремент" або "менший або рівний", #означає "рахувати" або "n разів", -:означає "половина" або "епсілон-рівність", :`(означають у свою чергу кінець зазначеної "половини", зв'язок між два дієслова в герунді та лівій дужці (використовується для групування). &*)означає "що-небудь прив'язане до множення" (3 пов'язані з множенням створює оператор "три рази") і кінець групування. =здійснює перевірку рівності або, в одинарному сенсі, самокласифікацію. ^:- силова сполука (ітерація дієслова). Оскільки багато дієслів J закінчуються двокрапкою, ... :-)
Джон Дворак

Через роки ... Удосконалений блок циклу: '- & 2 # (> & 1 * -: + 2 & | * +: +>: @ -:) ^: a:' -> -1 char. : P
randomra

Ще через роки ... <:#a:2&(<*|+|6&*%~)19 байт (-11)
миль

6

Гамбітна схема, 106 98 символів, 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 символів з визначити безпосередньо

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


Мене давно не було, але я помітив, що зазвичай люди розміщують 1 відповідь на кожній мові програмування.
jsedano

Вибачте, я про це не знав :)
Валентин КЛЕМЕНТ

Відредаговано для видалення Python.
Валентин КЛЕМЕНТ

1
Неправда! Люди, як правило, публікують одну відповідь на кожній мові програмування, але це тому, що вони намагаються не конкурувати безпосередньо з кимось іншим із коротшою відповіддю. Але ніхто не збирається скаржитися, якщо ви опублікуєте іншу відповідь тією ж мовою.
хлібниця

@breadbox не вірно. Я розміщую одну відповідь на кожну мову, якщо кожне рішення цікаве саме по собі порівняно з іншим. Якщо обидва рішення є такими ж цікавими, як обидва разом (один і той же алгоритм, ніяких цікавих мовних хитрощів), я публікую їх як одне. Зазвичай я не публікую декілька рішень, оскільки спочатку вибираю мову, потім вирішую проблему на тій мові - тоді мені зазвичай лінь писати те ж саме на іншій мові - або вирушаю в подорож, щоб вивчити ще одне програмування мова.
Джон Дворак

6

PowerShell: 77 74 71 70 61

Код для гольфу:

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

Примітки:

Спочатку я намагався взяти введення користувача, не примушуючи його до цілого числа, але це вийшло цікавим чином. Будь-які непарні входи обробляться неточно, але навіть введення спрацює нормально. Знадобилося мені хвилину, щоб зрозуміти, що відбувається.

Виконуючи множення чи додавання, PowerShell спочатку розглядає нетипізовані введення як рядок. Отже, '5'*3+1стає "5551" замість 16. Рівні входи поводилися чудово, оскільки PowerShell не має дії за замовчуванням для поділу на рядки. Навіть парні входи, які прогресували б через непарні числа, спрацювали нормально, оскільки, до моменту, коли PowerShell потрапив до непарного числа в циклі, змінна вже була примушена до цілого числа математичними операціями.

Завдяки Данко Дурбіч за вказівку, що я міг просто перевернути операцію множення, а не примушувати її передавати read-hostдо int, оскільки PowerShell базує свої операції на першому об’єкті.

Порада PowerShell Golfer: У деяких сценаріях, таких як цей, switchб'є if/else. Тут різниця склала 2 символи.

Ввічливість Данко Дурбіч : Для цього конкретного сценарію можна використовувати масив замість switch, щоб зберегти ще 8 символів!

Немає перевірки помилок на не цілі значення або цілі числа менше двох.

Якщо ви хочете перевірити сценарій, поставте ;$iбезпосередньо перед останнім закритим дужкою сценарію.

Я не впевнений, наскільки точно PowerShell обробляє цифри, які переходять у дуже великі значення, але я сподіваюся, що в якийсь момент втрачається точність. На жаль, я також сподіваюся, що з цим не можна багато зробити, не серйозно роздуваючи сценарій.


Код без вольфів, із коментарями:

# 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]
Данько Дурбич

2
Крім того, вам не потрібно конвертувати read-hostв число - просто змініть $i*3на 3*$i.
Данько Дурбич

Масив замість комутатора? Блискуче! І обмінюватися $i*3- чому я вже не придумав цього?
Іссі

1
param($i)for(;$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x- поміняйте хост читання на параметр, щоб отримати 56 байт . Спробуйте онлайн-посилання
TessellatingHeckler

6

80386 збірка, 16 байт

У цьому прикладі використовується синтаксис AT&T та конвенція виклику швидкого виклику, аргумент переходить у 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

Брахілог , 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

Пітон 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 байт.
Бакуріу

О, ви навіть можете отримати менше , ніж: [n/2,3*n+1][n%2].
кабінка

Це витончено!
Валентин КЛЕМЕНТ

Це питон 2.7? Я отримую помилку в Python 3.5.1? unsupported operand type(s) for -: 'str' and 'int'
Джордж

5

Сітківка , 43 байти

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

Здійснює введення та друкує вихідні дані унітарно.

Кожен рядок повинен мати свій власний файл. 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. Я думав, що збираюся роздушити цей виклик за допомогою постійного струму, але отримав лише 40. Я побачив вашу відповідь 27. Ну добре.
Цифрова травма

Я не бачив цього виклику, але деякий час переглянув питання про друк послідовності Collatz у постійному струмі. Мій підхід схожий на ваш, але програє байтом, тому я не бачу причин розміщувати його. Однак, коли я дивився на моє, щоб побачити, як легко перейти від друку кожного кроку до друку кількості кроків, я помітив щось, що може переграти байт від вашого… Оскільки послідовність Collatz завжди буде від 2 до 1, ви можете змінити свій умовний режим 2<xі позбутися його k. На всякий випадок, якщо ви хочете байт назад через чотири роки. : D
brhfl

4

мозковий ебать , 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

Шестикутник , 48 44 байт

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

Спробуйте в Інтернеті!

Розширено:

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

Зверніть увагу , що це не буде працювати на 1по гм ... причин . Чесно кажучи, я не дуже впевнений, як це працює вже. Все, що я знаю, це те, що код для непарних чисел запускається назад для парних чисел? Якось?

Нова версія набагато чистіша за попередню, але має ще кілька напрямків порівняно, а також закінчується помилкою поділу на нуль. Єдиний випадок, коли він не помиляється, це коли він справді поводиться 1правильно.


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

@ Сок так, тому я розмістив це замість того, щоб не шалено намагатися виправити це
Jo King

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

Рубін 1,9, 49 символів

Відповідь Python від Rubyfied Valentin CLEMENT , використовуючи стійкий лямбда-синтаксис. Розподілила його в одне твердження для додаткової нечитабельності.

(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
Дверна ручка

Проблема полягає в тому, що n==1це базовий випадок рекурсії. Поміщення n==2туди не поліпшило балів.
Джо З.

Ага, тоді ви можете просто замінити це: 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

> <>, 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, і обчислення послідовності може жити в одному рядку коду.

Редагувати: Збільшивши іншого символу, зрозумівши, що єдине додатне ціле число, яке може призвести до 1, є 2. Оскільки вихід програми не має значення для введення <2, генерація послідовностей може закінчитися, коли буде досягнуто 2, залишивши розмір стека будучи точною кількістю необхідних кроків.

Версія Previouser:

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

1
Ви можете \::2%:@5*1+2,*+:2=?
пограти в
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.