Conjetura de Collatz (OEIS A006577)


66

Esta es la conjetura de Collatz (OEIS A006577 ):

  • Comience con un número entero n > 1.
  • Repita los siguientes pasos:
    • Si n es par, divídalo por 2.
    • Si n es impar, multiplíquelo por 3 y agregue 1.

Está comprobado que para todos los enteros positivos hasta 5 * 2 60 , o aproximadamente 5764000000000000000 , n eventualmente se convertirá en 1 .

Su tarea es averiguar cuántas iteraciones se necesitan (de reducir a la mitad o triplicar más uno) para llegar a 1 .

Relevante xkcd :)

Reglas:

  • El código más corto gana.
  • Si se ingresa un número <2, o no es un número entero, o no es un número, la salida no importa.

Casos de prueba

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

Respuestas:



15

C - 50 47 caracteres

Desafortunadamente, el pequeño C requiere una cantidad horrible de código para E / S básicas, por lo que acortar todo eso ha hecho que la IU sea poco intuitiva.

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

Compilarlo con por ejemplo gcc -o 1 collatz.c. La entrada está en unario con dígitos separados por espacios, y encontrará la respuesta en el código de salida. Un ejemplo con el número 17:

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

1
return~-a?ahorra 1. También se debe guardar b++el traslado al ?caso b--.
ugoren

Jeje que estés doblando las reglas por lo tanto: P 1 para la creatividad y el uso de un lenguaje no se usa por lo general al golf
Pomo

Gracias ugoren! Debo haber estado borracho al escribirlo. :)
Fors

12

Perl 34 (+1) caracteres

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

Abusando $\para la salida final, como de costumbre. Ejecute con la -popción de línea de comando, la entrada se toma de stdin.

Salvado un byte debido a Elias Van Ootegem . Específicamente, la observación de que los dos siguientes son equivalentes:

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

Aunque un byte más, ahorra dos bytes acortando $_/2a solo .5.

Uso de la muestra:

$ echo 176 | perl -p collatz.pl
18

PHP 54 bytes

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

La archienemigo de Javascript para el Premio Cuchara de Madera parece haberse quedado un poco corta en este desafío. Sin embargo, no hay mucho espacio para la creatividad con este problema. La entrada se toma como un argumento de línea de comando.

Uso de la muestra:

$ php collatz.php 176
18

1
Me tomó un tiempo descubrir qué están haciendo los corchetes sin igual :)
marinus

1
La repetición $_en el ternario parece un desperdicio, puede afeitarse otro personaje mediante el uso de *=la siguiente manera: $\++,$_*=$_&1?3+1/$_:.5while$_>1}{. Multiplicar por 1/$_tiene el mismo efecto que +1, así que $_*=3+1/$_funciona bien
Elias Van Ootegem

@EliasVanOotegem $_*=3+1/$_es brillante, ¡gracias!
primo

11

Mathematica (35)

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

Uso:

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

No es una función válida, 10.3 se queja de un pícaro @ al final
CalculatorFeline

@ está llamando al argumento, no sé por qué estaba allí, solo una edición rápida
millas del

Hay que tener cuidado :)
CalculatorFeline

10

Como suelo hacer, comenzaré las respuestas con las mías.

JavaScript, 46 44 caracteres (se ejecuta en la consola)

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

¿Cuál es el punto de ~~ prompt () si dijiste que la salida no importa si no es un entero? Puedes guardar dos personajes deshaciéndote de ~~.
Resorath

@Resorath Ah, se olvidó del casting automático de JS: P gracias
Doorknob

9

Java, 165, 156, 154,134,131,129,128 , 126 (los lenguajes detallados también necesitan algo de amor)

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

Todo se hace dentro de la

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

Eso es malditamente hermoso hombre. Gracias a Pater Taylor !!!, y la idea de usar un bucle for fue robada a ugoren

Reemplacé Integer por Short.


1
Puede guardar fácilmente la longitud de i(,++y). Puede guardar dos más utilizando en <lugar de ==.
Peter Taylor

@PeterTaylor tienes razón, mis comparaciones serán más cortas con <, pero no entiendo la parte del incremento
previo

2
Los dos lados de su segundo ternario son estructuralmente idénticos, por lo que puede empujar el ternario al primer argumento de la llamada recursiva.
Peter Taylor

1
OH MI DIOS QUE ES BRILLANTE
jsedano 01 de

2
Sé que ha sido alrededor de 3,5 años, pero todavía se puede golf por 5 bytes : 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;}}Los cambios realizados: 1) Sustituido Short.valueOf(...)con new Short(...)de -4 bytes y 2) He puesto el x=x%2<1?x/2:x*3+1;en el cuerpo de la for-loop para deshacerse de la coma por -1 byte .
Kevin Cruijssen

9

Rebmu : 28

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

En un problema tan breve y complejo, es probable que GolfScript gane un cierto porcentaje contra Rebmu (si no es necesario decirlo, lea archivos de Internet o genere archivos JPG). Sin embargo, creo que la mayoría estaría de acuerdo en que la lógica del Golfscript no es tan fácil de seguir, y la pila ejecutable total que lo ejecuta es más grande.

Aunque el propio creador de Rebol, Carl Sassenrath , me dijo que encontró a Rebmu "ilegible", está ocupado y no tiene tiempo para practicar realmente la transformación de cerdo-latín a través de unmushing . Esto realmente se transforma simplemente en:

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

Tenga en cuenta que se necesitaba espacio para obtener una a: en lugar de una a . Esta es una "palabra clave". y el evaluador nota ese tipo de símbolo para activar la asignación.

Si se escribiera en forma abreviada (pero Rebol escrito torpemente), obtendría:

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

Rebol, como Ruby, evalúa los bloques hasta su último valor. El bucle UNTIL es una forma curiosa de bucle que no tiene condición de bucle, simplemente deja de bucle cuando su bloque se evalúa como algo no FALSO o NINGUNO. Entonces, en el punto en que 1 ==el resultado de asignar A (el argumento para rebmu) al resultado del condicional Collatz (cualquiera es un IF-ELSE que evalúa la rama que elige) ... el bucle se rompe.

J y K se inicializan al valor entero cero en Rebmu. Y como se mencionó anteriormente, todo se evalúa hasta el último valor. Entonces, una referencia J al final del programa significa que obtienes el número de iteraciones.

Uso:

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

8

Python repl, 48

No estoy convencido de que no haya una expresión más corta que n=3*n+1;n/=1+n%2*5;. Probablemente encontré una docena de expresiones diferentes de la misma longitud ...

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

editar: he encontrado otra solución que nunca competirá, pero es demasiado divertida para no compartirla.

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
Me duele el cerebro ahora.
daniero

1
@daniero la segunda solución es solo para ti.
stand

Oh wow. ¡Me siento honrado!
daniero

44
(n//2,n*3+1)[n%2]Es más corto.
Evpok

1
@Evpok no n/2funcionaría tan bien como sabemos que es incluso?
George

7

APL (31)

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

vieja respuesta, aún, 27:{1=⍵:0⋄2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}
Uriel

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

7

J, 30 caracteres

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

Resultó bastante más de lo deseado

uso:

   <:#-:`(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&*)`]es un gerundio compuesto por tres verbos, usado en tres ocasiones. -:significa "reducir a la mitad" (1+3&*)o (1+3*])codifica el paso de multiplicación y la ]terminación de las ayudas (de identidad).

  • 2&|+1&=forma un índice para el gerundio. literalmente, "el resto después de la división por dos más si es igual a uno".

  • #verb^:a:itera la función hasta que el resultado sea estable (aquí, forzado explícitamente), mientras recopila los pasos, luego los cuenta. Robado de @JB . <:disminuye el recuento de pasos en uno para alinearse con los requisitos de la pregunta.


66
Cada vez que veo una presentación J, cuento las caritas. Esto lo hace bastante bien: <:, #-:, :`(, &*), =), )^:.
primo

3
@primo agradable; quieres su explicación? :-) <:significa "decremento" o "menos o igual", #significa "conteo de" o "n veces", -:significa "reducir a la mitad" o "igualdad de épsilon", :`(significa a su vez el final de dicha "reducción a la mitad", el vínculo entre dos verbos en un gerundio y un paréntesis izquierdo (usado para agrupar). &*)significa "algo unido a la multiplicación" (3 unidos con la multiplicación crea el operador "multiplicado por tres") y el final de la agrupación. =realiza comprobaciones de igualdad o, en sentido unario, autoclasificación. ^:es la conjunción de poder (iteración verbal). Como muchos verbos J terminan con dos puntos, ... :-)
John Dvorak

Años después ... Bloque de bucle mejorado: '- & 2 # (> & 1 * -: + 2 & | * +: +>: @ -:) ^: a:' -> -1 char. : P
randomra

Más años después ... <:#a:2&(<*|+|6&*%~)19 bytes (-11)
millas

6

Esquema de Gambito, 106 98 caracteres, 40 paréntesis

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

91 89 caracteres con definir directamente

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


No he estado por mucho tiempo, pero he notado que generalmente las personas publican 1 respuesta por lenguaje de programación.
jsedano

Lo siento, no estaba al tanto de eso :)
Valentin CLEMENT

Editado para eliminar el Python.
Valentin CLEMENT

1
¡No es verdad! Las personas tienden a publicar una respuesta por lenguaje de programación, pero eso es porque están tratando de no competir directamente con otra persona con una respuesta más corta. Pero nadie se va a quejar si publica una respuesta diferente en el mismo idioma.
breadbox el

@breadbox no es cierto. Publico una respuesta por idioma si cada solución es interesante por sí misma en comparación con la otra. Si ambas soluciones son tan interesantes como ambas juntas (el mismo algoritmo, no hay trucos de lenguaje interesantes), las publico como una. Normalmente no publico múltiples soluciones porque primero elijo un idioma, luego resuelvo el problema en ese idioma, luego soy demasiado flojo para escribir lo mismo en un idioma diferente, o me embarco en un viaje para aprender otra programación idioma.
John Dvorak

6

PowerShell: 77 74 71 70 61

Código de golf:

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

Notas:

Originalmente intenté tomar la entrada del usuario sin forzarla a un número entero, pero eso se rompió de una manera interesante. Cualquier entrada impar se procesaría incorrectamente, pero incluso las entradas funcionarían bien. Me tomó un minuto darme cuenta de lo que estaba pasando.

Al realizar la multiplicación o suma, PowerShell trata primero la entrada sin escribir como una cadena. Entonces, se '5'*3+1convierte en '5551' en lugar de 16. Las entradas pares se comportaron bien porque PowerShell no tiene una acción predeterminada para la división contra cadenas. Incluso las entradas pares que progresarían a través de números impares funcionaron bien porque, para cuando PowerShell llegó a un número impar en el ciclo, la variable ya estaba forzada a un entero por las operaciones matemáticas de todos modos.

Gracias a Danko Durbic por señalar que podría simplemente invertir la operación de multiplicación y no tener que enviar read-hosta int ya que PowerShell basa sus operaciones en el primer objeto.

Consejo de golfista de PowerShell: Para algunos escenarios, como este, switchlate if/else. Aquí, la diferencia fue de 2 personajes.

Cortesía de Protip de Danko Durbic : ¡Para este escenario particular, se puede usar una matriz en lugar de switch, para guardar 8 caracteres más!

No hay comprobación de errores para valores no enteros o enteros menores de dos.

Si desea auditar la secuencia de comandos, coloque ;$ijusto antes de la última llave de cierre en la secuencia de comandos.

No estoy seguro de qué tan bien PowerShell maneja los números que progresan en valores muy grandes, pero espero que la precisión se pierda en algún momento. Desafortunadamente, también espero que no se pueda hacer mucho al respecto sin inflar seriamente el script.


Código sin golf, con comentarios:

# 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

Casos de prueba:

A continuación se muestran algunos ejemplos con la auditoría habilitada. También he editado el resultado para mayor claridad, agregando etiquetas a la entrada y al conteo final y colocando espacios para separar los valores de 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
---

Bits interesantes sobre los números de entrada que no son de los casos de prueba de la pregunta:


2
¡Agradable! Todavía puede acortarlo un poco, reemplazándolo switchcon$i=(($i/2),($i*3+1))[$i%2]
Danko Durbić

2
Además, no tiene que convertir read-hosta número, solo cambie $i*3a 3*$i.
Danko Durbić

¿Una matriz en lugar de un interruptor? ¡Brillante! Y cambiando, ¿ $i*3por qué no pensé en eso ya?
Iszi

1
param($i)for(;$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x- intercambie el host de lectura por un parámetro, para obtener 56 bytes . Enlace de prueba en línea
TessellatingHeckler

6

80386 conjunto, 16 bytes

Este ejemplo usa la sintaxis de AT&T y la convención de llamada de llamada rápida, el argumento entra en 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);

Aquí están los 16 bytes resultantes de código de máquina:

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

6

Brachylog , 16 bytes

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

Pruébalo en línea!

Explicación

         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.

Una solución alternativa en el mismo número de bytes:

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

Pruébalo en línea!

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

F # - 65 caracteres

let rec c n=function 1->n|i->c(n+1)(if i%2=0 then i/2 else i*3+1)

5

Python 68 58 54 52 caracteres

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

Gracias a Bakuriu y a Boothby por los consejos :)


Puede usar n%2and 3*n+1or n/2para guardar 5 caracteres. También en python2 puede eliminar la llamada a int, reduciendo el tamaño a 58 bytes.
Bakuriu

Oh, incluso se puede obtener más corto que: [n/2,3*n+1][n%2].
Boothby

Eso es ingenioso!
Valentin CLEMENT

¿Es este Python 2.7? ¿Recibo un error en Python 3.5.1? unsupported operand type(s) for -: 'str' and 'int'
george

5

Retina , 43 bytes

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

Toma entrada e imprime la salida en unario.

Cada línea debe ir a su propio archivo. 1 byte por archivo adicional agregado al conteo de bytes.

Puede ejecutar el código como un archivo con la -sbandera. P.ej:

> echo -n 1111111|retina -s collatz
1111111111111111

El algoritmo es un ciclo de hacer un paso de Collatz con el número unario y agregar un nuevo marcador de paso xal final de la cadena si el número no es 1.

Cuando el ciclo termina con 1, convertimos los marcadores a un número unario (eliminando el inicio 1) que es la salida deseada.


5

Gelatina , no competidora

12 bytes Esta respuesta no es competitiva, ya que el desafío es anterior a la creación de Jelly.

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

Pruébalo en línea!

Cómo funciona

×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 caracteres

Aplicando la magia negra de boothby :

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

No estoy realmente seguro si entiendo cómo, o eso , funciona.

Uso:
$ dc collatz.dc <<< 7
16

dc, 36 caracteres

Mi propia creación; un enfoque algo más tradicional, incluso aunque tuve que discutir un poco con el lenguaje para superar la falta de una elseparte en las ifdeclaraciones:

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

Internamente produce todos los números de la secuencia y los almacena en la pila, luego 1muestra el final y muestra la altura de la pila.


1
La paridad no es magia negra.
stand

1
No, ¡pero es un truco muy bueno! De hecho, yo mismo he hecho cosas similares, simplemente no lo pensé en este caso. Lo que me sorprendió por un segundo fue la división, pero lo entiendo: divides por seis, revocando la primera operación (* = 3, + = 1) con la segunda si la paridad era incorrecta, y debido a la división de enteros, la suma continúa lejos también, y básicamente hemos hecho / = 2. Muy inteligente :)
daniero

1
+1. Pensé que iba a aplastar este desafío con DC, pero solo llegué a 40. Vi la respuesta de 27. Oh bien.
Digital Trauma

No había visto este desafío, pero escribí un blog sobre la impresión de la secuencia de Collatz en cc. Mi enfoque es similar al suyo, pero pierde por un byte, así que realmente no veo una razón para publicarlo. Sin embargo, cuando estaba mirando el mío para ver cómo pasar fácilmente de imprimir cada paso a imprimir el número de pasos, vi algo que puede jugar un byte con el tuyo ... Dado que la secuencia de Collatz siempre irá de 2 a 1, puede cambiar su condicional 2<xay deshacerse de k. En caso de que quiera recuperar un byte después de cuatro años. : D
brhfl

4

brainfuck , 59 56 bytes

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

Pruébalo en línea! (Ligeramente modificado para facilitar su uso)

Entrada y salida como códigos de caracteres. Esto es más útil con celdas de tamaño arbitrario, pero aún puede funcionar con valores pequeños en tamaños de celda limitados.

Cómo funciona

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

Hexagonía , 48 44 bytes

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

Pruébalo en línea!

Expandido:

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

Tenga en cuenta que esto falla 1por uhh ... razones . Honestamente, ya no estoy seguro de cómo funciona esto. Todo lo que sé es que el código para números impares se ejecuta al revés para números pares. ¿De alguna manera?

La nueva versión es mucho más limpia que la anterior, pero tiene algunas direcciones más en comparación y también termina en un error de división por cero. El único caso en el que no produce errores es cuando realmente se maneja 1correctamente.


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

@Sok Sí, por eso lo publiqué en lugar de volverme loco tratando de arreglar eso
Jo King

3

C, 70 69 caracteres

Muy simple, sin trucos.
Lee la entrada de stdin.

a;
main(b){
    for(scanf("%d",&b);b-1;b=b%2?b*3+1:b/2)a++;
    printf("%d",a);
}

3

Q, 46

{i::0;{x>1}{i+:1;$[x mod 2;1+3*x;(_)x%2]}\x;i}

32 bytes con(#)1_(1<){(1+3*x;x%2)0=x mod 2}\
streetster

3

Ruby 1.9, 49 caracteres

Rubyfied Valentin CLEMENT responde a Python , utilizando la sintaxis lambda stabby. Se dividió en una declaración para mayor ilegibilidad.

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

Algunos gastos generales porque Ruby, a diferencia de Python, no está contento con mezclar números con booleanos.


3

C ++ ( 51 48)

Esta es una función recursiva que hace esto; La lectura de entrada viene por separado.

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

Estoy seguro de que puedo hacer algún tipo de "y / o" truco con las == 0cosas, pero no tengo idea de cómo.


Puede quitar ==0e intercambiar los lados del condicional
Pomo de la puerta

Además, no es necesario manejarlo n==1porque especifiqué en la pregunta que el número siempre es mayor que 1
Pomo de la puerta

El problema es que n==1es el caso base de recursión. Poner n==2allí no mejoraría la puntuación.
Joe Z.

Ah, entonces podría reemplazarlo con esto: return~-n?e intercambiar los lados condicionales
Pomo de la puerta

. n==1== n<2.
CalculatorFeline

3

~ - ~! (Sin comentarios) - 71 53

Obviamente, este lenguaje no es el mejor para el golf, ya que carece de una gran cantidad de funcionalidades nativas, pero esa es su belleza.

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

Primero, configure '''su entrada. La función ''se puede llamar entonces %como entrada y devolverá la respuesta, así:

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

Esto devolverá ~~~~~. Realmente funciona para n==1(se repite para siempre n==0).

Como siempre con este lenguaje, no probado.


3

JavaScript (ES6) - 29 caracteres

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

Crea una función fque acepta un único argumento y devuelve el número de iteraciones.

JavaScript: 31 caracteres

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

Asume que la entrada está en la variable ny crea una variable cque contiene el número de iteraciones (y también se enviará ca la consola como su último comando).



3

Perl 6, 40 bytes

Método de función recursiva, según Valentin CLEMENT y daniero : 40 caracteres

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

Método de lista perezosa: 32 caracteres

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

3

> <>, 27 26 23 bytes

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

Al igual que las otras respuestas> <>, esto construye la secuencia en la pila. Una vez que la secuencia alcanza 2, el tamaño de la pila es el número de pasos dados.

Gracias a @Hohmannfan, ahorró 3 bytes mediante un método muy inteligente de calcular el siguiente valor directamente. La fórmula utilizada para calcular el siguiente valor en la secuencia es:

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

La fracción asigna números pares a 0.5 y números impares a 3. Multiplicar por ny sumar n%2completa el cálculo, ¡no es necesario elegir el siguiente valor!

Edición 2: Aquí está la versión pre @ Hohmannfan:

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

El truco aquí es que ambos 3n+1y n/2se calculan en cada paso de la secuencia, y el que se eliminará de la secuencia se elige después. Esto significa que el código no necesita bifurcarse hasta alcanzar 1, y el cálculo de la secuencia puede vivir en una línea de código.

Editar: Golfed otro personaje después de darse cuenta de que el único entero positivo que puede conducir a 1 es 2. Como la salida del programa no importa para la entrada <2, la generación de secuencia puede terminar cuando se alcanza 2, dejando el tamaño de la pila siendo el número exacto de pasos requeridos.

Versión anterior:

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

1
Puede jugar golf a 23 si desmarca la segunda línea aún más:\::2%:@5*1+2,*+:2=?
Hohmannfan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.