Congettura di Collatz (OEIS A006577)


66

Questa è la congettura di Collatz (OEIS A006577 ):

  • Inizia con un numero intero n > 1.
  • Ripeti i seguenti passi:
    • Se n è pari, dividerlo per 2.
    • Se n è dispari, moltiplicalo per 3 e aggiungi 1.

È dimostrato che per tutti gli interi positivi fino a 5 * 2 60 , o circa 5764000000000000000 , n diventerà infine 1 .

Il tuo compito è scoprire quante iterazioni sono necessarie (dimezzare o triplicare-più-uno) per raggiungere 1 .

Rilevante xkcd :)

Regole:

  • Il codice più corto vince.
  • Se viene immesso un numero <2, o un numero intero o un non numero, l'output non ha importanza.

Casi test

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

Risposte:



15

C - 50 47 caratteri

Purtroppo la povera piccola C richiede una terribile quantità di codice per l'I / O di base, quindi abbreviare tutto ciò ha reso l'IU leggermente poco intuitiva.

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

Compilalo con per esempio gcc -o 1 collatz.c. L'input è unario con cifre separate da spazio e troverai la risposta nel codice di uscita. Un esempio con il numero 17:

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

1
return~-a?salva 1. Anche il passaggio b++al ?caso dovrebbe salvare b--.
Ugoren,

Hehe stai piegando così tanto le regole : P +1 per la creatività e l'utilizzo di una lingua che di solito non viene utilizzata per il golf
Maniglia della porta

Grazie ugoren! Devo essere stato ubriaco quando lo scrivo. :)
Fors,

12

Perl 34 (+1) caratteri

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

Abuso $\per l'output finale, come al solito. Esegui con l' -popzione della riga di comando, l'input viene preso da stdin.

Salvato un byte grazie a Elias Van Ootegem . In particolare, l'osservazione che i seguenti due sono equivalenti:

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

Sebbene sia più lungo di un byte, consente di risparmiare due byte accorciando $_/2a solo .5.

Esempio di utilizzo:

$ echo 176 | perl -p collatz.pl
18

PHP 54 byte

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

L'archnemesi di Javascript per il Wooden Spoon Award sembra non essere stata all'altezza di questa sfida. Tuttavia, non c'è molto spazio per la creatività con questo problema. L'input viene considerato come argomento della riga di comando.

Esempio di utilizzo:

$ php collatz.php 176
18

1
Mi ci è voluto un po 'per capire cosa stanno facendo le parentesi senza pari :)
Marin

1
Ripetendo $_nel ternario sembra uno spreco, è possibile radersi un altro personaggio utilizzando *=in questo modo: $\++,$_*=$_&1?3+1/$_:.5while$_>1}{. Moltiplicare per 1/$_ha lo stesso effetto +1, quindi $_*=3+1/$_funziona bene
Elias Van Ootegem,

@EliasVanOotegem $_*=3+1/$_è eccezionale, grazie!
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

Non è una funzione valida, 10.3 si lamenta di una canaglia @ alla fine
CalculatorFeline

@ sta chiamando l'argomento, non so perché fosse lì, solo una rapida modifica
miglia

Devo stare attento :)
CalculatorFeline

10

Come faccio di solito, inizierò le risposte con le mie.

JavaScript, 46 44 caratteri (eseguito su console)

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

Qual è il punto di ~~ prompt () se hai detto che l'output non ha importanza se si tratta di un non intero? Puoi salvare due personaggi eliminando ~~.
Resorath,

@Resorath Ah, ho dimenticato il casting automatico di JS: P grazie
Maniglia

9

Java, 165, 156, 154.134.131.129.128 , 126 (anche le lingue verbose hanno bisogno di amore)

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

Tutto è fatto all'interno del for

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

È un uomo bellissimo da morire. Grazie a Pater Taylor !!!, e l'idea di usare un ciclo for è stata rubata da Ugoren

Ho sostituito Integer per Short.


1
Puoi facilmente salvare la lunghezza di i(,++y). Puoi salvarne altri due usando <invece di ==.
Peter Taylor,

@PeterTaylor hai ragione, i miei confronti saranno più brevi con <, ma non capisco la parte del pre-incremento
jsedano

2
Le due parti del secondo ternario sono strutturalmente identiche, quindi puoi spingere il ternario nel primo argomento della chiamata ricorsiva.
Peter Taylor,

1
OH MIO DIO CHE È
GENIALE

2
So che è stato di circa 3,5 anni, ma si può ancora golf è da 5 byte : 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;}}modifiche fatte: 1) Sostituito Short.valueOf(...)con new Short(...)per il -4 byte e 2) ho messo il x=x%2<1?x/2:x*3+1;nel corpo del for-loop per sbarazzarsi della virgola per -1 byte .
Kevin Cruijssen,

9

Rebmu : 28

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

Su un problema così breve e matematico, GolfScript probabilmente vincerà di qualche percento contro Rebmu (se non è necessario dirlo, leggere file da Internet o generare file JPG). Tuttavia, penso che molti concorderebbero che la logica di Golfscript non è altrettanto facile da seguire e lo stack eseguibile totale che lo esegue è più grande.

Sebbene lo stesso creatore di Rebol, Carl Sassenrath, mi abbia detto di aver trovato Rebmu "illeggibile", è impegnato e non ha il tempo di esercitarsi davvero nella trasformazione simile a un maiale latino attraverso il mushing . Questo è semplicemente trasformato in:

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

Si noti che lo spazio era richiesto per ottenere un a: anziché un a . Questa è una "parolaccia!" e il valutatore nota quel tipo di simbolo per attivare l'assegnazione.

Se fosse scritto in Rebol non abbriato (eppure scritto in modo goffo), otterresti:

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

Rebol, come Ruby, valuta i blocchi fino al loro ultimo valore. Il loop UNTIL è una forma curiosa di loop che non accetta alcuna condizione di loop, ma interrompe il loop quando il suo blocco restituisce qualcosa che non è FALSE o NONE. Quindi al punto che 1 ==il risultato dell'assegnazione di A (l'argomento a rebmu) al risultato del condizionale Collatz (o è un IF-ELSE che valuta il ramo che sceglie) ... il ciclo si interrompe.

J e K sono inizializzati al valore intero zero in Rebmu. E come già detto, l'intera cosa viene valutata all'ultimo valore. Quindi un riferimento J alla fine del programma significa che ottieni il numero di iterazioni.

Uso:

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

8

Python sostitu, 48

Non sono convinto che non ci sia un'espressione più breve di n=3*n+1;n/=1+n%2*5;. Probabilmente ho trovato una dozzina di espressioni diverse della stessa lunghezza ...

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

modifica: ho trovato un'altra soluzione che non potrà mai contendere, ma è troppo divertente per non condividere.

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
Adesso mi fa male il cervello.
daniero,

1
@daniero la seconda soluzione è solo per te.
stand,

Oh wow Sono onorato!
daniero,

4
(n//2,n*3+1)[n%2]è più corto.
Evpok,

1
@Evpok non n/2funzionerebbe bene come sappiamo che è pari?
George,

7

APL (31)

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

vecchia risposta, ancora, 27:{1=⍵:0⋄2|⍵:1+∇1+3×⍵⋄1+∇⍵÷2}
Uriel

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

7

J, 30 caratteri

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

Si è rivelato un po 'più lungo del desiderato

utilizzo:

   <:#-:`(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&*)`]è un gerundio composto da tre verbi, usato in tre occasioni. -:significa "dimezzare" (1+3&*)o (1+3*])codifica la fase di moltiplicazione e ](identità) aiuta la terminazione.

  • 2&|+1&=forma un indice per il gerundio. letteralmente, "il resto dopo la divisione per due più se è uguale a uno".

  • #verb^:a:itera la funzione fino a quando il risultato non è stabile (qui, forzato esplicitamente), mentre raccoglie i passaggi, quindi li conta. Rubato da @JB . <:riduce il conteggio dei passi di uno per allinearlo ai requisiti della domanda.


6
Ogni volta che vedo una presentazione J, conto le faccine. Questo si fa abbastanza bene: <:, #-:, :`(, &*), =), )^:.
primo

3
@primo nice; vuoi la loro spiegazione? :-) <:significa "decremento" o "minore o uguale", #significa "conteggio di" o "n volte", -:significa "metà" o "epsilon-uguaglianza", :`(significa a sua volta la fine di detta "metà", il legame tra due verbi in un gerundio e una parentesi sinistra (usati per raggruppare). &*)significa "sth. bonded to the moltiplication" (3 bonded with moltiplication crea l'operatore "times three") e la fine del raggruppamento. =esegue il controllo dell'uguaglianza o, nel senso unario, l'autoclassificazione. ^:è la congiunzione del potere (iterazione del verbo). Poiché molti verbi J terminano con due punti, ... :-)
John Dvorak,

Anni dopo ... Blocco loop migliorato: '- & 2 # (> & 1 * -: + 2 & | * +: +>: @ -:) ^: a:' -> -1 char. : P
randomra,

Altri anni dopo ... <:#a:2&(<*|+|6&*%~)19 byte (-11)
miglia

6

Schema di gioco, 106 98 caratteri, 40 parentesi

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

91 89 caratteri con definisci direttamente

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


Non sono in giro da molto tempo, ma ho notato che di solito le persone pubblicano 1 risposta per linguaggio di programmazione.
jsedano,

Mi dispiace, non ne ero a conoscenza :)
Valentin CLEMENT

Modificato per rimuovere quello di Python.
Valentin CLEMENT,

1
Non vero! Le persone tendono a pubblicare una risposta per linguaggio di programmazione, ma questo perché stanno cercando di non competere direttamente con qualcun altro con una risposta più breve. Ma nessuno si lamenterà se pubblichi una risposta diversa nella stessa lingua.
breadbox

@breadbox non vero. Pubblico una risposta per lingua se ogni soluzione è interessante da sola rispetto all'altra. Se entrambe le soluzioni sono interessanti quanto entrambe insieme (lo stesso algoritmo, nessun trucco linguistico interessante), le inserisco come una. Normalmente non pubblico più soluzioni perché scelgo prima una lingua, quindi risolvo il problema in quella lingua - quindi di solito sono troppo pigro per scrivere la stessa in una lingua diversa - o intraprendo un viaggio per imparare ancora un'altra programmazione linguaggio.
John Dvorak,

6

PowerShell: 77 74 71 70 61

Codice golfizzato:

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

Appunti:

Inizialmente ho provato a prendere l'input dell'utente senza forzarlo a un numero intero, ma questo si è rotto in modo interessante. Qualsiasi input dispari verrebbe elaborato in modo impreciso, ma anche gli input funzionerebbero bene. Mi ci è voluto un minuto per capire cosa stesse succedendo.

Quando si esegue la moltiplicazione o l'aggiunta, PowerShell considera innanzitutto l'input non digitato come una stringa. Quindi, '5'*3+1diventa '5551' anziché 16. Gli input pari si sono comportati bene perché PowerShell non ha un'azione predefinita per la divisione rispetto alle stringhe. Anche gli input pari che progredivano attraverso i numeri dispari funzionavano bene perché, quando PowerShell arrivava a un numero dispari nel ciclo, la variabile era già stata forzata a un numero intero dalle operazioni matematiche.

Grazie a Danko Durbic per la segnalazione , ho potuto semplicemente invertire l'operazione di moltiplicazione e non dover eseguire il cast read-hostsu int poiché PowerShell basa le sue operazioni sul primo oggetto.

Suggerimento per i golfisti di PowerShell: per alcuni scenari, come questo, switchbatte if/else. Qui, la differenza era di 2 caratteri.

Protip per gentile concessione di Danko Durbic : per questo particolare scenario, è possibile utilizzare un array al posto di switch, per salvare altri 8 personaggi!

Non vi è alcun errore nel controllo di valori non interi o interi inferiori a due.

Se desideri controllare lo script, inseriscilo ;$iappena prima dell'ultima parentesi graffa dello script.

Non sono sicuro di quanto bene PowerShell gestisca numeri che progrediscono in valori molto grandi, ma mi aspetto che a un certo punto la precisione venga persa. Sfortunatamente, mi aspetto anche che non ci sia molto da fare al riguardo senza gonfiare seriamente la sceneggiatura.


Codice non golfato, con commenti:

# 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

Casi test:

Di seguito sono riportati alcuni esempi con il controllo abilitato. Ho anche modificato l'output un po 'per chiarezza, aggiungendo etichette all'input e al conteggio finale e mettendo in spaziatura per separare i valori di 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
---

Bit interessanti sui numeri di input che non provengono dai casi di test della domanda:


2
Bello! Puoi ancora accorciarlo un po ', sostituendolo switchcon$i=(($i/2),($i*3+1))[$i%2]
Danko Durbić il

2
Inoltre, non è necessario convertire read-hostin numero, basta cambiare $i*3in 3*$i.
Danko Durbić,

Un array invece di switch? Brillante! E scambiandosi $i*3: perché non ci avevo già pensato?
Iszi,

1
param($i)for(;$i-ne1;$x++){$i=(($i/2),(3*$i+1))[$i%2]}$x- scambiare l'host di lettura con un parametro per ottenere 56 byte . Provalo Link online
TessellatingHeckler

6

80386 assembly, 16 byte

In questo esempio viene utilizzata la sintassi AT&T e la convenzione di chiamata di chiamata rapida, l'argomento entra in 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);

Ecco i 16 byte risultanti del codice macchina:

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

6

Brachylog , 16 byte

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

Provalo online!

Spiegazione

         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 soluzione alternativa con lo stesso numero di byte:

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

Provalo online!

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

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 caratteri

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

Grazie a Bakuriu e boothby per i suggerimenti :)


Puoi usare n%2and 3*n+1or n/2per salvare 5 caratteri. Inoltre in python2 è possibile rimuovere la chiamata a int, riducendo la dimensione a 58 byte.
Bakuriu,

Oh, si può anche ottenere più breve di quello: [n/2,3*n+1][n%2].
stand dal

È carino!
Valentin CLEMENT,

Questo è Python 2.7? Viene visualizzato un errore in Python 3.5.1? unsupported operand type(s) for -: 'str' and 'int'
george,

5

Retina , 43 byte

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

Accetta input e stampa output in modo unario.

Ogni riga dovrebbe andare nel proprio file. 1 byte per ogni file aggiuntivo aggiunto al conteggio byte.

È possibile eseguire il codice come un file con il -sflag. Per esempio:

> echo -n 1111111|retina -s collatz
1111111111111111

L'algoritmo è un ciclo di fare un passo di Collatz con il numero unario e aggiungere un nuovo marcatore di passo xalla fine della stringa se il numero non è 1.

Quando il loop termina con 1, convertiamo i marker in un numero unario (rimuovendo il comando iniziale 1) che è l'output desiderato.


5

Gelatina , non competitiva

12 byte Questa risposta non è competitiva, poiché la sfida precede la creazione di Jelly.

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

Provalo online!

Come funziona

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

Applicazione della magia nera di Boothby :

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

Non sono davvero sicuro di capire come - o quello - funzioni.

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

dc, 36 caratteri

La mia stessa creazione; un approccio un po 'più tradizionale, anche se ho dovuto lottare un po' con il linguaggio per superare la mancanza di una elseparte delle ifdichiarazioni:

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

Internamente produce tutti i numeri della sequenza e li memorizza nello stack, quindi apre il finale 1e visualizza l'altezza dello stack.


1
La parità non è magia nera.
stand dal

1
No, ma è un trucco molto pulito lì! In realtà ho fatto cose simili da solo, in questo caso non ci ho pensato. Ciò che mi ha inciampato per un secondo è stata la divisione, ma ho capito: dividi per sei, ripristinando la prima operazione (* = 3, + = 1) con la seconda se la parità era sbagliata, e a causa della divisione intera l'aggiunta va anche via, e in pratica abbiamo fatto / = 2. Molto intelligente :)
daniero il

1
+1. Pensavo che avrei schiacciato questa sfida con dc, ma ho raggiunto solo il 40. Ho visto la tua 27 risposta. Oh bene.
Digital Trauma,

Non avevo visto questa sfida, ma ho scritto un po 'di blog sulla stampa della sequenza di Collatz in DC. Il mio approccio è simile al tuo ma perde di un byte, quindi non vedo davvero un motivo per pubblicarlo. Tuttavia, quando guardavo il mio per vedere come passare facilmente dalla stampa di ogni passaggio alla stampa del numero di passaggi, ho notato qualcosa che può golf un byte dal tuo ... Poiché la sequenza di Collatz passerà sempre da 2 a 1, puoi cambiare il tuo condizionale 2<xe liberarti di k. Nel caso in cui si desideri un byte indietro dopo quattro anni. : D
brhfl,

4

brainfuck , 59 56 byte

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

Provalo online! (Leggermente modificato per facilità d'uso)

Input e output come codici carattere. Ciò è più utile con celle di dimensioni arbitrarie, ma può comunque funzionare con valori piccoli in celle di dimensioni limitate.

Come funziona

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

Esagonia , 48 44 byte

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

Provalo online!

Allargato:

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

Nota che questo non funziona 1per uh ... ragioni . Onestamente, non sono più sicuro di come funzioni. Tutto quello che so è che il codice per i numeri dispari viene eseguito all'indietro per i numeri pari? In qualche modo?

La nuova versione è molto più pulita della precedente, ma ha alcuni più direzionali in confronto e termina anche con un errore di divisione per zero. L'unico caso in cui non si verifica è quando si gestisce effettivamente 1correttamente.


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

@Sok Sì, è per questo che l'ho pubblicato invece di impazzire cercando di sistemarlo
Jo King

3

C, 70 69 caratteri

Abbastanza semplice, niente trucchi.
Legge input da stdin.

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


3

Ruby 1.9, 49 caratteri

La risposta Python di Rubinfied Valentin CLEMENT , usando la sintassi di stabby lambda. È stato inserito in un'unica istruzione per una maggiore illeggibilità.

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

Qualche sovraccarico perché Ruby, a differenza di Python, non è contento di mescolare i numeri con i booleani.


3

C ++ ( 51 48)

Questa è una funzione ricorsiva che lo fa; la lettura dell'ingresso viene fornita separatamente.

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

Sono sicuro di poter fare una sorta di "e / o" trucco con le == 0cose, ma non ho idea di come.


È possibile rimuovere ==0e scambiare i lati del condizionale
Maniglia della porta

Inoltre, non è necessario gestirlo n==1perché ho specificato nella domanda che il numero è sempre maggiore di 1
Maniglia della porta

Il problema è che n==1è il caso di ricorsione di base. Metterci n==2lì non migliorerebbe il punteggio.
Joe Z.

Ah, allora potresti semplicemente sostituirlo con questo: return~-n?e scambiare i lati condizionali
Maniglia della porta

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

3

~ - ~! (Nessun commento) - 71 53

Questo linguaggio non è ovviamente il migliore per giocare a golf poiché manca di una grande quantità di funzionalità native, ma questa è la sua bellezza.

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

Innanzitutto, imposta il '''tuo input. La funzione ''può quindi essere chiamata con %il suo input e restituirà la risposta, in questo modo:

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

Questo tornerà ~~~~~. In realtà funziona per n==1(si avvolge per sempre con n==0).

Come sempre con questa lingua, non testato.


3

JavaScript (ES6) - 29 caratteri

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

Crea una funzione fche accetta un singolo argomento e restituisce il numero di iterazioni.

JavaScript - 31 caratteri

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

Presuppone che l'input si trovi nella variabile ne crea una variabile cche contiene il numero di iterazioni (e verrà anche emessa csulla console come ultimo comando).



3

Perl 6, 40 byte

Metodo di funzione ricorsiva, secondo Valentin CLEMENT e daniero : 40 caratteri

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

Metodo dell'elenco pigro: 32 caratteri

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

3

> <>, 27 26 23 byte

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

Come le altre risposte <>, questo crea la sequenza nello stack. Una volta che la sequenza raggiunge 2, la dimensione della pila è il numero di passi effettuati.

Grazie a @Hohmannfan, ho salvato 3 byte con un metodo molto intelligente per calcolare direttamente il valore successivo. La formula utilizzata per calcolare il valore successivo nella sequenza è:

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

La frazione associa i numeri pari a 0,5 e i numeri dispari a 3. La moltiplicazione ne l'aggiunta n%2completa il calcolo - non è necessario scegliere il valore successivo!

Modifica 2: Ecco la versione pre @ Hohmannfan:

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

Il trucco qui è che entrambi 3n+1e n/2vengono calcolati ad ogni passo della sequenza, e quello da eliminare dalla sequenza viene scelto in seguito. Ciò significa che il codice non deve essere ramificato fino al raggiungimento di 1 e il calcolo della sequenza può vivere su una riga di codice.

Modifica: golfato da un altro carattere dopo aver realizzato che l'unico numero intero positivo che può portare a 1 è 2. Poiché l'output del programma non ha importanza per l'input <2, la generazione della sequenza può terminare quando viene raggiunto 2, lasciando la dimensione dello stack essendo il numero esatto di passaggi richiesti.

Versione precedente:

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

1
Puoi giocare a golf a 23 se \::2%:@5*1+2,*+:2=?
sblocchi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.