Рекурсивна колацева конституція


21

В гіпотезах Коллатц постулату , що якщо взяти будь-яке позитивне ціле число, а потім повторити наступний алгоритм досить раз:

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

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

Ви вже гольфували, обчислюючи, скільки часу потрібно, щоб дістатися до 1 , тому я подумав, що я трохи перемкнув би речі.

Починаючи з заданого натурального числа, обчисліть, скільки часу потрібно, щоб дістатися до 1 (його "час зупинки"). Потім знайдіть час зупинки цього номера.

Повторюйте, поки не досягнете рівня 1, або поки не досягнете абсолютно довільної межі 100 ітерацій. У першому випадку надрукуйте, скільки ітерацій знадобилось. В останньому випадку надрукуйте "Fail" або якийсь інший послідовний результат на ваш вибір, доки це не ціле число 1≤n≤100. Ви не можете вивести порожній рядок для цієї опції. Однак виведення цілого числа поза діапазону [1, 100] дозволено.

Приклади:

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

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

Оцінка балів

Оскільки це , відповідь з найменшою кількістю байтів виграє.


Відповіді:




6

Attache , 40 байт

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

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

Це нова мова, яку я виголосив. Мені хотілося обійтись, щоб зробити належну інфіксовану мову, і це результат: матч-математика. Ура?

Пояснення

Це композиція з кількох функцій. Це такі функції:

  • PeriodicSteps[CollatzSize@Max&1]Це дає функцію, яка застосовує свій аргумент до тих пір, поки результати не містять повторюваний елемент. Ця функція, CollatzSize@Max&1застосовується CollatzSizeдо більшої частини входу і 1, щоб уникнути недійсного введення 0для CollatSize.
  • `#- оператор з котируванням; застосовуючи монадично в цьому сенсі, він отримує розмір свого аргументу
  • `-&3це зв’язана функція, яка пов'язує аргумент 3із функцією `-, яка читається як "мінус 3". Це тому, що додаток PeriodicSteps дає 0s, які потрібно враховувати. (Він також акуратно обробляє цифри поза межами типу 5, на яке відображається карта -1.)

1
Чи дійсно використання вашої рідної мови дозволено? Не можете ви просто створити ланцюг для кожного кодового гольфу, використовуючи лише деякі байти?
Tweakimp

2
@Tweakimp Звичайно, створення (та використання) власної мови дозволено. Але модифікувати його таким чином, щоб завдання була єдиною командою (після публікації виклику) - це стандартна лазівка.
caird coinheringaahing

2
@Tweakimp, якщо це змушує тебе відчувати себе краще, я створив цю функцію ще до того, як побачив це завдання. Я мовний дизайнер, тому саме цим і займаюся.
Конор О'Браєн

Більш загальним було питання про те, чи дозволяються самостійно виготовлені мови, а не негативне твердження про те, що ви використовували свої власні.
Tweakimp

4

J , 49 45 байт

-4 байти завдяки коротшому коду послідовності Collatz, взятому з коментаря @ randomra тут .

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

Виводи 101за недійсні результати.

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

Пояснення

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

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

Знаходження довжини послідовності Колац

Цей розділ коду наступний

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

Ось пояснення:

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

На жаль, дієслово застосувати ( ^:), коли сказано зберігати результати, також зберігає початкове значення, тож це означає, що ми (як завжди) відключені на одне. Звідси ми віднімаємо 1.

Знаходження довжини рекурсивної послідовності

(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
Якщо ви не заперечуєте , використовуючи розділ заголовка, це буде , можливо , більш точно продемонструвати свою відповідь
Конор О'Брайен

@ ConorO'Brien я взагалі не знаю - я не знав, як його відформатувати як такий (але відтепер я буду красти ваші). Спасибі
cole

1
А н у т я м е!
Conor O'Brien

1
38 байт з *i.~(<101)1&(#@}.a:2&(<*|{%~,*+1+])])]повинні бути еквівалентними
миль


3

JavaScript (ES6), 57 байт

Повертається, trueколи це не вдалося. Повертається 0за 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

Тестові кейси


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

@JonathanFrech Справді. Виявляється, обидва результати були однаково недійсними.
Арнольд

3

APL (Dyalog Unicode) , 39 60 53 52 49 байт

-3 байти завдяки @ngn

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

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

Використовує код @ngn для Collatz, але раніше використовував код @ Uriel.

Ось стара версія, яка не відповідала специфікації:

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

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


2

Лушпиння , 21 байт

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

Спробуйте в Інтернеті! Повертається -1після відмови, 0на вході 1.

Пояснення

←€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 байт

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

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

Повертається, 101коли кількість повторень перевищує 100.


1
Ласкаво просимо до PPCG! Ця відповідь не зовсім коректна, тому що всі подані функції потребують багаторазового використання . Я думаю, що ви можете це виправити, вставивши m=0у свій f(мабуть, навіть скориставшись порожнім forінструментом для збереження ;).
Мартін Ендер

2

Чистота , 146 ... 86 байт

-11 байт завдяки Ерджану Йохансену

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

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

Як часткова функція буквальна.

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

Відміняється, hd of []якщо кількість повторень перевищує 100.
Виходить із Heap Fullвведеннями вище ~, 2^23якщо не вказати більший розмір купи.


1
Я починаю розуміти деякий синтаксис «Чистий» (чим він відрізняється від Haskell) з ваших відповідей ... ви можете скоротити це за допомогою допоміжної функції j f l n=hd[u\\1<-iterate f n&u<-l].
Ørjan Johansen

@ ØrjanJohansen Дякую!
Οurous

Вам не потрібна \a=...aчастина, вона цікавить. (Або ета зменшує.)
Шрян Йохансен

@ ØrjanJohansen о, пропустив це, дякую!
Οurous




1

APL NARS, 115 байт, 63 символи

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

Можливо, з використанням циклів було б зрозуміліше ... Є 4 функції, 2 вкладені та рисоривні, і перша лише для визначення та ініціалізації до = 0, змінна d, розглядається з 2-ї функції як глобальний лічильник змінних.

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

Ця 3-а функція - це функція, яка повертає скільки дзвінків існує для вирішення гіпотези Колатца для її аргументу

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

Це 2-а функція, якщо вона має arg = 1, зупинити її рекурсію і повернути d кількість часу, яку вона називає сама-1; інакше, якщо виклик себе більше 99 разів зупиняє його рекурсію і повертає -1 (не працює), інше обчислює гіпотезу Колатца для його аргументу і називає себе для значення довжини послідовності Колатца. Для мене, навіть якщо все це здається запущеним, може бути великою проблемою, якщо визначена глобальна змінна та одна змінна у функції з однойменною назвою, коли програміст розглядає її як просто локальну змінну.

  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, Загальні, ...) Lisp, 105 байт

Повертає t для ітерацій> 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))))

Розширено:

(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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.