Congettura ricorsiva di Collatz


21

La congettura di Collatz postula che se prendi un numero intero positivo, ripeti il ​​seguente algoritmo abbastanza volte:

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

alla fine finirai su 1. Sembra sempre funzionare, ma non è mai stato provato che lo faccia sempre.

Hai già giocato a golf calcolando quanto tempo ci vuole per arrivare a 1 , quindi ho pensato di cambiare un po 'le cose.

Partendo da un dato intero positivo, calcola quanto tempo impiega per arrivare a 1 (il suo "tempo di arresto"). Quindi trova il tempo di arresto di quel numero.

Ripetere l'operazione fino a quando non si arriva a 1 o fino al limite completamente arbitrario di 100 iterazioni. Nel primo caso, stampa quante iterazioni ci sono volute. In quest'ultimo caso, stampa "Fail" o qualche altro output coerente di tua scelta, purché non sia un numero intero 1≤n≤100. Non è possibile generare una stringa vuota per questa opzione. L'emissione di un numero intero al di fuori dell'intervallo [1, 100], tuttavia, è consentita.

Esempi:

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

Come ho calcolato 10^100e 12345678901234567890usando una lingua che supporta solo reali per quella dimensione, se la tua lingua è più accurata potresti ottenere risultati diversi per quelli.

punteggio

Poiché si tratta di , vince la risposta con il minor numero di byte.


Risposte:




6

Attache , 40 byte

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

Provalo online!

Questa è una nuova lingua che ho creato. Volevo andare in giro a creare un linguaggio infix adeguato, e questo è il risultato: un knock-off matematico. Evviva?

Spiegazione

Questa è una composizione di alcune funzioni. Queste funzioni sono:

  • PeriodicSteps[CollatzSize@Max&1]Ciò produce una funzione che applica il suo argomento fino a quando i risultati contengono un elemento duplicato. Questa funzione CollatzSize@Max&1si applica CollatzSizeal maggiore dell'input e 1, per evitare l'input non valido 0a CollatSize.
  • `#è un operatore quotato; se applicato monadicamente in questo senso, ottiene la dimensione del suo argomento
  • `-&3è una funzione legata, che lega l'argomento 3alla funzione `-, che si legge come "meno 3". Questo perché l'applicazione PeriodicSteps produce 0s, che devono essere contabilizzati. (Gestisce anche in modo ordinato numeri fuori limite come 5, a cui è associata -1.)

1
L'uso della tua lingua è davvero permesso? Non riesci a creare una lingua per ogni codegolf con solo alcuni byte?
Tweakimp,

2
@Tweakimp Naturalmente è consentito creare (e utilizzare) la propria lingua. Ma modificarlo in modo che un'attività sia un singolo comando (dopo che la sfida è stata pubblicata) è una scappatoia standard.
caird coinheringaahing

2
@Tweakimp se ti fa sentire meglio, avevo progettato questa funzione prima di vedere questa sfida. Sono un designer di lingue, quindi è quello che faccio.
Conor O'Brien,

Era più una domanda generale se sono permesse le lingue autoprodotte, non un'affermazione negativa che tu abbia usato la tua.
Tweakimp,

4

J , 49 45 byte

-4 byte grazie al codice di sequenza Collatz più breve tratto dal commento di @ randomra qui .

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

Output 101per risultati non validi.

Provalo online!

Spiegazione

Non sorprende che questa spiegazione sia diventata rapidamente obsoleta. Lo lascerò nei termini della vecchia risposta a 49 byte che avevo, che includo di seguito. Se vuoi un aggiornamento, fammelo sapere. Il modo in cui trova la lunghezza della sequenza ricorsiva rimane lo stesso, ho appena usato un metodo di sequenza Collatz più breve.

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

Trovare la lunghezza della sequenza di Collatz

Questa sezione del codice è la seguente

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

Ecco la spiegazione:

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

Sfortunatamente, il verbo apply ( ^:) quando viene detto di archiviare i risultati memorizza anche il valore iniziale, quindi significa che (come sempre) siamo esclusi da uno. Quindi perché sottraiamo 1.

Trovare la lunghezza della sequenza ricorsiva

(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
Se non ti dispiace usare la sezione dell'intestazione, questo forse mostrerà più accuratamente la tua risposta
Conor O'Brien,

@ ConorO'Brien Non lo so affatto - non sapevo davvero come formattarlo come tale (ma da ora in poi ruberò i tuoi). Grazie
Cole

1
A n y t i m E!
Conor O'Brien,

1
38 byte con *i.~(<101)1&(#@}.a:2&(<*|{%~,*+1+])])]dovrebbero essere equivalenti
miglia

4

C (gcc) , 75 byte

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

Restituisce -1per n>=100iterazioni.

Provalo online!

C (gcc) , 73 byte

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

Restituisce 0per n>=100iterazioni.

Provalo online!


3

JavaScript (ES6), 57 byte

Ritorna truequando fallisce. Restituisce 0per 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

Casi test


Sono scettico se il tuo programma capita di calcolare il risultato corretto oltre a overflow / inesattezza o se piuttosto l'OP ha derivato i loro risultati usando un linguaggio con implementazioni di numeri simili (suppongo che non abbiano calcolato tutti i casi di test a mano).
Jonathan Frech,

@JonathanFrech Indeed. Si scopre che entrambi i risultati erano ugualmente non validi.
Arnauld

3

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

-3 byte grazie a @ngn

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

Provalo online!

Utilizza il codice @ngn per Collatz, ma precedentemente utilizzato il codice @ Uriel.

Ecco la vecchia versione che non soddisfaceva le specifiche:

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

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


2

Buccia , 21 byte

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

Provalo online! Restituisce -1in caso di errore, 0in ingresso1 .

Spiegazione

←€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 byte

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

Provalo online!

Restituisce 101quando il numero di iterazioni supera 100.


1
Benvenuti in PPCG! Questa risposta non è del tutto valida, poiché tutti gli invii di funzioni devono essere riutilizzabili . Penso che tu possa risolvere questo problema inserendolo m=0nel tuo f(probabilmente anche usando l' forintiailizzatore attualmente vuoto per salvarne uno a ;).
Martin Ender,

2

Pulito , 146 ... 86 byte

-11 byte grazie 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]

Come una funzione parziale letterale.

Provalo online!

Si interrompe hd of []se il numero di iterazioni supera 100.
Esce con Heap Fullper input sopra ~ a 2^23meno che non si specifichi una dimensione heap maggiore.


1
Sto iniziando a capire alcune sintassi Clean (in quanto differisce da Haskell) dalle tue risposte ... puoi accorciarle con una funzione di aiuto j f l n=hd[u\\1<-iterate f n&u<-l].
Ørjan Johansen,

@ ØrjanJohansen Grazie!
Οuroso

Non hai bisogno della \a=...aparte, si cura. (O eta si riduce.)
Ørjan Johansen

@ ØrjanJohansen oh, mi sono perso, grazie!
Οuroso

1

Python 2 , 99 98 97 byte

  • Ho salvato un byte usando c and t or finvece di t if c else f.
  • Salvato un byte emettendo -1invece di fo 'f'per input senza interruzione.
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)")

Provalo online!


1

BiwaScheme , 151 caratteri

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

Puoi provarlo qui .


1

R , 119 107 byte

Parzialmente utilizza il codice Collatz di Jarko Dubbeldam da qui . Restituisce 0per> 100 iterazioni (errore).

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

Provalo online!


1

APL NARS, 115 byte, 63 caratteri

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

Probabilmente usando i loop sarebbe più chiaro ... Ci sono 4 funzioni, 2 nidificate e ricorsive, e la prima solo per definire e inizializzare a = 0, la variabile d, vista dalla seconda funzione come contatore di variabili globali.

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

Questa terza funzione, sarebbe la funzione che restituisce quante chiamate ci sono per risolvere la congettura di Collatz per il suo arg

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

Questa è la 2a funzione, se ha il suo arg = 1, ferma la sua ricorsione e restituisce d il numero di volte in cui viene chiamata stessa-1; altrimenti se stesso viene chiamato più di 99 volte, interrompe la sua ricorsione e restituisce -1 (fallisce), altrimenti calcola la congettura di Collatz per il suo arg e chiama se stesso per il valore della lunghezza della sequenza di Collatz. Per me, anche se tutto ciò sembra funzionare potrebbe essere un grosso problema se viene definita una variabile globale e una variabile in una funzione con lo stesso nome, quando il programmatore la vede come una variabile locale.

  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, Common, ...) Lisp, 105 byte

Restituisce t per iterazioni> 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))))

Allargato:

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