Analizzare sequenze simili a Collatz


12

Definiamo una sequenza simile a Collatzs con 4 numeri interi positivi:

  • n valore iniziale
  • d > 1 divisore
  • m > 1 moltiplicatore
  • i incremento

(Nella sequenza originale di Collatz d = 2 m = 3e i = 1.)

Dati questi numeri interi sverranno creati nel modo seguente:

  • s(0) = n
  • se k > 0e s(k-1) mod d = 0pois(k) = s(k-1) / d
  • se k > 0e s(k-1) mod d != 0pois(k) = s(k-1) * m + i

Una sequenza di esempio con d = 2, m = 3, i = 5e n = 80sarà s = 80, 40, 20, 10, 5, 20, 10, 5, 20, ....

Ogni sequenza raggiungerà valori più alti di qualsiasi dato limite (ovvero la sequenza è divergente) o entrerà in un ciclo infinito se per alcuni te u( t!=u) l' s(t) = s(u)uguaglianza sarà vera.

Nel nostro problema se il valore di un elemento sequenza è maggiore di 10^9o non c'è ripetizione di elemento prima di1000 dell'elemento th, la sequenza è considerata divergente.

L'obiettivo

Dovresti scrivere un programma o una funzione che accetta gli interi positivi d me icome input e output tutti i diversi tipi finali delle sequenze (loop infiniti e divergenza) quali i valori inizialin = 1, 2, 3, ... 999, 1000 possono produrre.

Dettagli di input

  • L'input è una stringa o un elenco (o l'equivalente più vicino nella tua lingua) che rappresenta (nel modo comune) tre numeri interi positivi d, me iin quell'ordine. de lo msono almeno 2. Nessuno dei due numeri è maggiore di 100.

Dettagli di output

La specifica di output è un po 'prolissa. Vale la pena dare un'occhiata agli esempi prima.

  • Dovresti produrre l'output standard (o l'alternativa più vicina) o restituire una stringa.
  • Se è possibile una sequenza divergente, la prima riga dovrebbe essere DIVERGENT.
  • Una rappresentazione univoca del ciclo di una sequenza è la rotazione in cui il numero più piccolo è l'ultimo separato da spazi. Ad esempio, se s = 2 1 4 2 1 4 2 1il ciclo è 4 2 1.
  • In ogni riga successiva dovresti generare ogni ciclo univoco esattamente una volta preceduto dalla parola LOOP. Per esempioLOOP 4 2 1
  • I loop dovrebbero essere in ordine crescente rispetto al loro ultimo elemento.
  • Il trascinamento di newline è facoltativo.

Esempi:

Le prime righe sono gli input e le seguenti fino a quando una riga vuota sono gli output.

2 3 1
LOOP 4 2 1

2 2 6
LOOP 8 4 2 1
LOOP 12 6 3

3 7 8
DIVERGENT
LOOP 15 5 43 309 103 729 243 81 27 9 3 1
LOOP 22 162 54 18 6 2
LOOP 36 12 4

3 9 1
DIVERGENT

6 9 9
DIVERGENT
LOOP 18 3 36 6 1
LOOP 27 252 42 7 72 12 2
LOOP 45 414 69 630 105 954 159 1440 240 40 369 3330 555 5004 834 139 1260 210 35 324 54 9 90 15 144 24 4
LOOP 81 738 123 1116 186 31 288 48 8
LOOP 99 900 150 25 234 39 360 60 10
LOOP 126 21 198 33 306 51 468 78 13

10 10 10
LOOP 20 2 30 3 40 4 50 5 60 6 70 7 80 8 90 9 100 10 1

93 91 92
DIVERGENT
LOOP 2185 198927 2139 23
LOOP 4278 46

Implementazione di riferimento in Python 3 su Ideone.

Questo è il golf da codice, quindi vince l'ingresso più breve.

Risposte:


5

Pitone 3, 269 254 252 246 byte

d,m,i=eval(input())
S=set()
for n in range(1,1001):
 T=X=()
 while len(T)**3<1e9>=n:
  T=(n,)+T;n=[n//d,n*m+i][n%d>0]
  if n in T:I=T.index;L=T[:I(n)+1];M=I(min(L));X=L[M:]+L[:M]
 S|={X}
for x in sorted(S):print(x and"LOOP"or"DIVERGENT",*x[::-1])

(Ora 10 volte più lento per risparmiare qualche byte. Tipico golf da codice.)

Immettere un elenco tramite STDIN (ad es [2, 3, 1].). Sto pensando che ci deve essere un modo migliore di standardizzare i cicli ...

L'approccio è piuttosto semplice: prova tutti i 1000 numeri e prendi solo gli output unici. Tuttavia, ci sono due piccoli trucchi lì dentro:

  • I loop sono rappresentati da tuple non vuote , ma soprattutto la divergenza è rappresentata da una tupla vuota . Questo va bene perché:

    • Non si rompe sortede apparirà anche prima di tutte le tuple ad anello
    • Ci consente di selezionare una stringa tramite x and"LOOP"or"DIVERGENT"
    • *()[::-1] non influenza print
  • I loop sono costruiti all'indietro per trasformare "ordinamento crescente per ultimo elemento" in "ordinamento crescente per primo elemento", che elimina la necessità di passare un lambda in sorted .

Invio precedente, 252 byte

d,m,i=eval(input())
def f(n,T=()):
 x=[n//d,n*m+i][n%d>0];I=T.index
 if x in T:L=T[:I(x)+1];M=I(min(L));return L[M:]+L[:M]
 return()if(T[1000:]or x>1e9)else f(x,(x,)+T)
for x in sorted(set(map(f,range(1,1001)))):print(x and"LOOP"or"DIVERGENT",*x[::-1])

Questo è molto più veloce.

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.