Hipoteza rekurencyjna Collatz

21

W Collatz Conjecture postulaty że jeśli wziąć dowolną dodatnią liczbę całkowitą, a następnie powtórzyć tyle razy następujący algorytm:

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

ostatecznie skończysz jako 1. Wygląda na to, że zawsze działa, ale nigdy nie udowodniono, że zawsze działa.

Grałeś już w golfa, obliczając ile czasu zajmuje dotarcie do 1 , więc pomyślałem, że trochę zmienię.

Zaczynając od podanej dodatniej liczby całkowitej, oblicz, ile czasu zajmuje dotarcie do 1 (jej „czasu zatrzymania”). Znajdź czas zatrzymania tego numeru.

Powtarzaj tę czynność, aż dojdziesz do 1 lub do całkowicie arbitralnego limitu 100 iteracji. W pierwszym przypadku wydrukuj ile iteracji to zajęło. W tym drugim przypadku wypisz „Fail” lub inny spójny wynik według własnego wyboru, o ile nie jest to liczba całkowita 1≤n≤100. Nie możesz wypisać pustego ciągu dla tej opcji. Wyprowadzenie liczby całkowitej spoza zakresu [1, 100] jest jednak dozwolone.

Przykłady:

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

Jak obliczyłem 10^100i 12345678901234567890używając języka, który obsługuje tylko liczby rzeczywiste dla tego rozmiaru, jeśli Twój język jest dokładniejszy, możesz uzyskać inne wyniki dla nich.

Punktacja

Ponieważ jest to , wygrywa odpowiedź z najmniejszą ilością bajtów.

DonielF
źródło

Odpowiedzi:

9

Python 2 , 70 bajtów

f=lambda n,k=0,j=0:n-1and-~f(k*[n/2,n*3+1][n%2]or f(j/99or n,1),k,j+1)

Zwraca 199 za sto lub więcej iteracji.

Wypróbuj online!

Dennis
źródło
6

Attache , 40 bajtów

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

Wypróbuj online!

To jest nowy język, który stworzyłem. Chciałem zająć się tworzeniem poprawnego języka, a to jest wynik: podróbka matematyki. Brawo?

Wyjaśnienie

Jest to kompozycja kilku funkcji. Te funkcje to:

  • PeriodicSteps[CollatzSize@Max&1]Daje to funkcję, która stosuje swój argument, aż wyniki zawierają zduplikowany element. Ta funkcja CollatzSize@Max&1ma zastosowanie CollatzSizedo większej wartości wejściowej i 1, aby uniknąć nieprawidłowej wartości wejściowej 0dla CollatSize.
  • `#jest notowanym operatorem; zastosowane monadycznie w tym sensie, uzyskuje rozmiar swojego argumentu
  • `-&3to funkcja powiązana, która wiąże argument 3z funkcją o `-treści „minus 3”. Wynika to z faktu, że aplikacja PeriodicSteps daje wyniki 0s, które należy uwzględnić. (To także starannie obsługuje liczby poza granicami, takie jak 5, które mapują -1.)
Conor O'Brien
źródło
1
Czy używanie własnego języka jest naprawdę dozwolone? Nie możesz po prostu utworzyć języka dla każdego kodegolfa, który używa tylko niektórych bajtów?
Tweakimp
2
@Tweakimp Oczywiście tworzenie (i używanie) własnego języka jest dozwolone. Ale zmodyfikowanie go tak, aby zadanie było pojedynczym poleceniem (po wysłaniu wyzwania), jest standardową luką.
caird coinheringaahing
2
@Tweakimp, jeśli dzięki temu poczujesz się lepiej, zaprojektowałem tę funkcję, zanim zobaczyłem to wyzwanie. Jestem projektantem języka, więc to właśnie robię.
Conor O'Brien
To było bardziej ogólne pytanie, czy dozwolone są własne języki, a nie negatywne stwierdzenie, że używasz własnego.
Tweakimp
4

J , 49 45 bajtów

-4 bajty dzięki krótszemu kodowi sekwencji Collatz pobranemu z komentarza @ randomra tutaj .

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

Dane wyjściowe 101dla nieprawidłowych wyników.

Wypróbuj online!

Wyjaśnienie

Nic dziwnego, że to wyjaśnienie szybko się zdezaktualizowało. Zostawię to w kategoriach starej 49-bajtowej odpowiedzi, którą otrzymałem, którą poniżej. Jeśli chcesz aktualizacji, daj mi znać. Sposób, w jaki odnajduje długość sekwencji rekurencyjnej, pozostaje taki sam, właśnie zastosowałem krótszą metodę Sekwencji Collatza.

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

Znalezienie długości sekwencji Collatz

Ta sekcja kodu jest następująca

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

Oto wyjaśnienie:

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

Niestety, czasownik zastosuj ( ^:), gdy zostanie wyświetlony monit o zapisywanie wyników, przechowuje również wartość początkową, więc oznacza to, że (jak zawsze) jesteśmy wyłączeni o jeden. Dlatego odejmujemy 1.

Znalezienie długości sekwencji rekurencyjnej

(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).
kapusta
źródło
1
Jeśli nie przeszkadza sekcję nagłówka, to być może bardziej precyzyjnie zaprezentować swoją odpowiedź
Conor O'Brien
@ ConorO'Brien W ogóle nie wiem - tak naprawdę nie wiedziałem, jak go sformatować jako taki (ale od teraz będę go kradł). Dzięki
cole
1
A n y t ja m e!
Conor O'Brien
1
38 bajtów z *i.~(<101)1&(#@}.a:2&(<*|{%~,*+1+])])]powinno być równoważnych
mile
4

C (gcc) , 75 bajtów

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

Zwraca -1dla n>=100iteracji.

Wypróbuj online!

C (gcc) , 73 bajty

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

Zwraca 0dla n>=100iteracji.

Wypróbuj online!

Steadybox
źródło
3

JavaScript (ES6), 57 bajtów

Zwraca, truegdy zawiedzie. Zwraca 0za 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

Przypadki testowe

Arnauld
źródło
Jestem sceptyczny, jeśli Twój program oblicza poprawny wynik oprócz przepełnienia / niedokładności lub jeśli OP uzyskał wyniki przy użyciu języka o podobnej liczbie implementacji (zakładam, że nie obliczył ręcznie wszystkich przypadków testowych).
Jonathan Frech
@JathanathanFrech Rzeczywiście. Okazuje się, że oba wyniki były jednakowo nieprawidłowe.
Arnauld
3

APL (Dyalog Unicode) , 39 60 53 52 49 bajtów

-3 bajty dzięki @ngn

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

Wypróbuj online!

Używa kodu @ngn dla Collatz, ale wcześniej używał kodu @ Uriel.

Oto stara wersja, która nie spełniała specyfikacji:

{1=⍵:01+∇{1=⍵:02|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}⍵}
Zacharý
źródło
2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2->1+∇⊃⍵⌽0 1+.5 3×⍵
ngn
2

Perl 6 , 56 bajtów

{($_,{($_,{$_%2??$_*3+1!!$_/2}...1)-1}...1).head(102)-1}

Wypróbuj online!

Zwraca 101sekwencję nie kończącą się.

Sean
źródło
2

Łuska , 21 bajtów

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

Wypróbuj online! Zwraca -1w przypadku awarii 0na wejściu 1.

Wyjaśnienie

←€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.
Zgarb
źródło
2

C (gcc) , 70 73 bajtów

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

Wypróbuj online!

Zwraca, 101gdy liczba iteracji przekroczy 100.


źródło
1
Witamy w PPCG! Ta odpowiedź nie jest całkiem poprawna, ponieważ wszystkie przesłane funkcje muszą być wielokrotnego użytku . Myślę, że możesz to naprawić, wstawiając m=0do swojego f(prawdopodobnie nawet korzystając z obecnie pustego fornarzędzia do usuwania, aby go zapisać ;).
Martin Ender
2

Czysty , 146 ... 86 bajtów

-11 bajtów dzięki Ø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]

Jako dosłowność funkcji częściowej.

Wypróbuj online!

Przerywa, hd of []jeśli liczba iteracji przekracza 100.
Wyjście z Heap Fulldla wartości wejściowych powyżej ~, 2^23chyba że podasz większy rozmiar sterty.

Obrzydliwe
źródło
1
Zaczynam rozumieć składnię Clean (ponieważ różni się od Haskell) od twoich odpowiedzi ... możesz ją skrócić za pomocą funkcji pomocnika j f l n=hd[u\\1<-iterate f n&u<-l].
Ørjan Johansen
@ ØrjanJohansen Thanks!
Οurous
Nie potrzebujesz tej \a=...aczęści, to curry. (Lub eta zmniejsza.)
Ørjan Johansen
@ ØrjanJohansen oh, przegapiłem to, dzięki!
Οurous
1

Python 2 , 99 98 97 bajtów

  • Zapisano bajt za pomocą c and t or fzamiast t if c else f.
  • Zapisano bajt, wysyłając dane -1zamiast flub 'f'dla danych wejściowych bez zatrzymania.
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)")

Wypróbuj online!

Jonathan Frech
źródło
1

BiwaScheme , 151 znaków

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

Możesz spróbować tutaj .

Andrea Ciceri
źródło
1

R , 119 107 bajtów

Częściowo używa kodu collatz Jarko Dubbeldam stąd . Zwraca 0dla> 100 iteracji (błąd).

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

Wypróbuj online!

rturnbull
źródło
1

APL NARS, 115 bajtów, 63 znaków

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

Prawdopodobnie przy użyciu pętli byłoby to bardziej jasne ... Istnieją 4 funkcje, 2 zagnieżdżone i pobudzające, a pierwsza tylko do definiowania i inicjalizacji na = 0, zmienna d, widziana z 2. funkcji jako licznik zmiennej globalnej.

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

Ta trzecia funkcja byłaby funkcją zwracającą liczbę wywołań dla rozwiązania hipotezy Collatza dla jej argumentu

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

Jest to druga funkcja, jeśli jej argument = 1, zatrzymaj jej rekurencję i zwróć d liczbę razy, gdy zostanie ona nazwana sobą-1; w przeciwnym razie, jeśli sam zostanie wywołany więcej niż 99 razy, zatrzymaj jego rekurencję i zwróć -1 (niepowodzenie), w przeciwnym razie oblicz hipotezę Collatza dla jej argumentu i wywołaj wartość długości sekwencji Collatza. Dla mnie nawet jeśli wszystko wydaje się działać, może być dużym problemem, jeśli jest zdefiniowana zmienna globalna i jedna zmienna w funkcji o tej samej nazwie, gdy programista widzi ją jako zmienną lokalną.

  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
RosLuP
źródło
1

(Emacs, Common, ...) Lisp, 105 bajtów

Zwraca t dla iteracji> 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))))

Rozszerzony:

(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)
użytkownik84207
źródło