Conjetura recursiva de Collatz

21

La conjetura de Collatz postula que si toma un número entero positivo, repita el siguiente algoritmo suficientes veces:

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

eventualmente terminarás en 1. Parece que siempre funciona, pero nunca se ha demostrado que siempre funcione.

Ya has jugado al golf calculando cuánto tiempo lleva llegar a 1 , así que pensé en cambiar un poco las cosas.

Comenzando con un entero positivo dado, calcule cuánto tiempo lleva llegar a 1 (su "tiempo de detención"). Luego encuentra el tiempo de detención de ese número.

Repita hasta llegar a 1, o hasta llegar al límite completamente arbitrario de 100 iteraciones. En el primer caso, imprima cuántas iteraciones tomó. En el último caso, imprima "Fail" o algún otro resultado consistente de su elección, siempre que no sea un número entero 1≤n≤100. No puede generar una cadena vacía para esta opción. Sin embargo, se permite generar un número entero fuera del rango [1, 100].

Ejemplos:

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

Como calculé 10^100y 12345678901234567890usando un idioma que solo admite reales para ese tamaño, si su idioma es más preciso, puede obtener resultados diferentes para ellos.

Tanteo

Como se trata de , gana la respuesta con la menor cantidad de bytes.

DonielF
fuente
Continuemos esta discusión en el chat .
cole

Respuestas:

9

Python 2 , 70 bytes

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)

Devuelve 199 para cien o más iteraciones.

Pruébalo en línea!

Dennis
fuente
6

Agregado , 40 bytes

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

Pruébalo en línea!

Este es un nuevo lenguaje que hice. Quería hacer un lenguaje infijo adecuado, y este es el resultado: una imitación matemática. Hurra?

Explicación

Esta es una composición de algunas funciones. Estas funciones son:

  • PeriodicSteps[CollatzSize@Max&1]Esto produce una función que aplica su argumento hasta que los resultados contienen un elemento duplicado. Esta función, CollatzSize@Max&1se aplica CollatzSizea la entrada mayor y 1, para evitar la entrada no válida 0a CollatSize.
  • `#es un operador cotizado; cuando se aplica monádicamente en este sentido, obtiene el tamaño de su argumento
  • `-&3es una función vinculada, que une el argumento 3a la función `-, que se lee como "menos 3". Esto se debe a que la aplicación PeriodicSteps produce 0s, que deben tenerse en cuenta. (También maneja de forma ordenada números fuera de los límites, como 5, qué mapa -1).
Conor O'Brien
fuente
1
¿Está realmente permitido usar su propio idioma? ¿No puedes crear un idioma para cada codegolf con solo usar algunos bytes?
Tweakimp
2
@Tweakimp Por supuesto, está permitido crear (y usar) tu propio idioma. Pero modificarlo para que una tarea sea un solo comando (después de que se publica el desafío) es una laguna estándar.
caird coinheringaahing
2
@Tweakimp si te hace sentir mejor, había diseñado esta función antes de ver este desafío. Soy diseñador de idiomas, así que eso es lo que hago.
Conor O'Brien
Fue más una pregunta general si se permiten los lenguajes hechos a sí mismos, no una afirmación negativa de que usaste la tuya.
Tweakimp
4

J , 49 45 bytes

-4 bytes gracias al código de secuencia de Collatz más corto tomado del comentario de @ randomra aquí .

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

Salidas 101para resultados no válidos.

Pruébalo en línea!

Explicación

Como era de esperar, esta explicación se ha vuelto obsoleta rápidamente. Lo dejaré en términos de la respuesta anterior de 49 bytes que tenía, que incluyo a continuación. Si quieres una actualización, avísame. La forma en que encuentra la longitud de la secuencia recursiva sigue siendo la misma, acabo de usar un método de secuencia de Collatz más corto.

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

Encontrar la longitud de la secuencia de Collatz

Esta sección del código es la siguiente

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

Aquí está la explicación:

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

Desafortunadamente, el verbo apply ( ^:) cuando se le dice que almacene los resultados también almacena el valor inicial, por lo que significa que estamos (como siempre) desactivados por uno. Por eso restamos 1.

Encontrar la longitud de la secuencia recursiva

(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).
col
fuente
1
Si no le importa usar la sección de encabezado, esto quizás muestre su respuesta con mayor precisión
Conor O'Brien el
@ ConorO'Brien No sé nada, realmente no sabía cómo formatearlo como tal (pero de ahora en adelante robaré el tuyo). Gracias
cole
1
A n y t i m e!
Conor O'Brien
1
38 bytes con *i.~(<101)1&(#@}.a:2&(<*|{%~,*+1+])])]deberían ser equivalentes
millas
4

C (gcc) , 75 bytes

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

Devoluciones -1para n>=100iteraciones.

Pruébalo en línea!

C (gcc) , 73 bytes

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

Devoluciones 0para n>=100iteraciones.

Pruébalo en línea!

Steadybox
fuente
3

JavaScript (ES6), 57 bytes

Regresa truecuando falla. Devoluciones 0para 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

Casos de prueba

Arnauld
fuente
Soy escéptico si su programa calcula el resultado correcto aparte del desbordamiento / inexactitud o si el OP derivó sus resultados usando un lenguaje con implementaciones de números similares (supongo que no calcularon todos los casos de prueba a mano).
Jonathan Frech
@JonathanFrech De hecho. Resulta que ambos resultados fueron igualmente inválidos.
Arnauld
3

APL (Dyalog Unicode) , 39 60 53 52 49 bytes

-3 bytes gracias a @ngn

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

Pruébalo en línea!

Utiliza el código @ngn para Collatz, pero anteriormente utilizó el código @ Uriel.

Aquí está la versión anterior que no cumplía con las especificaciones:

{1=⍵:01+∇{1=⍵:02|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}⍵}
Zacharý
fuente
2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2->1+∇⊃⍵⌽0 1+.5 3×⍵
ngn
2

Casco , 21 bytes

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

Pruébalo en línea! Retornos -1en caso de falla, 0en la entrada 1.

Explicación

←€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
fuente
2

C (gcc) , 70 73 bytes

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

Pruébalo en línea!

Devuelve 101cuando el número de iteraciones excede 100.


fuente
1
Bienvenido a PPCG! Esta respuesta no es válida, porque todas las presentaciones de funciones deben ser reutilizables . Creo que puede solucionar esto insertando m=0en su f(probablemente incluso haciendo uso del forintiailizador actualmente vacío para guardar uno a ;).
Martin Ender
2

limpia , 146 ... 86 bytes

-11 bytes gracias a Ø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]

Como una función parcial literal.

Pruébalo en línea!

Cancela con hd of []si el número de iteraciones excede de 100.
Sale con las Heap Fullentradas de más de ~ a 2^23menos que especifique un tamaño de almacenamiento dinámico mayor.

Οurous
fuente
1
Estoy empezando a entender algo de sintaxis Clean (ya que difiere de Haskell) de sus respuestas ... puede acortar eso con una función auxiliar j f l n=hd[u\\1<-iterate f n&u<-l].
Ørjan Johansen
@ ØrjanJohansen ¡Gracias!
Οurous
No necesitas la \a=...aparte, curry. (O eta reduce.)
Ørjan Johansen
@ ØrjanJohansen oh, perdí eso, gracias!
Precioso
1

Python 2 , 99 98 97 bytes

  • Guardado un byte usando en c and t or flugar det if c else f .
  • Se guardó un byte al generar en -1lugar de fo 'f'para entradas sin detener.
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)")

Pruébalo en línea!

Jonathan Frech
fuente
1

BiwaScheme , 151 caracteres

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

Puedes probarlo aquí .

Andrea Ciceri
fuente
1

R , 119107 bytes

Utiliza parcialmente el código collatz de Jarko Dubbeldam desde aquí . Devuelve 0para> 100 iteraciones (falla).

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

Pruébalo en línea!

rturnbull
fuente
1

NARS APL, 115 bytes, 63 caracteres

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

Probablemente usando bucles sería más claro ... Hay 4 funciones, 2 anidadas y enriquecedoras, y la primera solo para definir e inicializar a = 0, la variable d, vista desde la 2ª función como un contador variable global.

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

Esta 3ª función, sería la función que devuelve cuántas llamadas hay para resolver la conjetura de Collatz para su arg

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

Esta es la 2ª función, si tiene su arg = 1, detiene su recursión y devuelve d la cantidad de veces que se llama a sí misma-1; de lo contrario, si se llama a sí mismo más de 99 veces, detenga su recursión y devuelva -1 (falla); de lo contrario, calcule la conjetura de Collatz para su arg y se llame a sí mismo para el valor de longitud de la secuencia de Collatz. Para mí, incluso si todo esto parece ejecutado, podría ser un gran problema si se define una variable global y una variable en una función del mismo nombre, cuando el programador lo ve como una variable local.

  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
fuente
1

(Emacs, Common, ...) Lisp, 105 bytes

Devuelve t para iteraciones> 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))))

Expandido:

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