Genera la sequenza SUDSI


15

La sequenza SUDSI ( su m, d ifference, s wap, i ncrement) è una curiosa sequenza di numeri interi che sembra esibire un comportamento piuttosto caotico. Può essere generato come segue:

Lasciate che S sia una lista infinita dei numeri naturali: 1 2 3 4 5 6 .... Let S i denotare la sola indicizzato i -esimo elemento di S . Quindi inizialmente S 1 è 1, S 2 è 2, ecc. (Non c'è S 0 ).

A partire da S 1 e S 2 ...

  • Calcola la loro somma: sum = S1 + S2
  • Calcola la loro differenza assoluta (la più grande meno la più piccola): diff = |S1 - S2|
  • Scambia i due valori in S sugli indici della somma e della differenza:swap(Ssum, Sdiff)

  • Incrementa gli indici di S con cui stai lavorando. Quindi la prossima volta calcolerai la somma e la differenza di S 2 e S 3 , e il tempo successivo sarà S 3 e S 4 , ecc.

  • Ripeti questo processo indefinitamente.

Ecco le prime fasi di S mentre viene applicato questo processo. Le parentesi []racchiudono i due valori che stanno per essere sommati e differenziati.

S originale :

[1 2] 3 4 5 6 7 8 9 10 11 12 ...

Dopo aver scambiato S 3 ( 3 = 1 + 2) e S 1 ( 1 = |1 - 2|):

3 [2 1] 4 5 6 7 8 9 10 11 12 ...

Dopo aver scambiato S 3 e S 1 :

1 2 [3 4] 5 6 7 8 9 10 11 12 ...

Dopo aver scambiato S 7 e S 1 :

7 2 3 [4 5] 6 1 8 9 10 11 12 ...

Dopo aver scambiato S 9 e S 1 :

9 2 3 4 [5 6] 1 8 7 10 11 12 ...

Dopo aver scambiato S 11 e S 1 :

11 2 3 4 5 [6 1] 8 7 10 9 12 ...

Dopo aver scambiato S 7 e S 5 :

11 2 3 4 1 6 [5 8] 7 10 9 12 ...

eccetera.

La sequenza SUDSI è definita come la sequenza dei primi elementi in ciascuno di questi elenchi. Quindi i primi termini della sequenza SUDSI sono 1 3 1 7 9 11 11.

Ecco i primi 200 termini della sequenza SUDSI (20 per riga):

1 3 1 7 9 11 11 11 15 15 19 19 19 19 19 19 19 19 19 19 
19 19 19 19 19 19 19 19 57 59 59 59 59 59 59 59 59 59 77 79 
81 83 85 87 89 91 91 91 91 91 91 91 91 91 91 91 91 91 115 115 
121 123 125 127 127 127 127 127 137 139 141 143 145 147 147 147 147 147 147 147 
147 147 147 147 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 
167 167 167 167 209 211 211 211 211 211 221 223 223 223 223 223 223 223 223 223 
223 223 243 243 243 243 243 243 257 259 261 263 263 263 263 263 263 263 263 263 
263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 263 
263 263 325 327 329 331 331 331 331 331 331 331 331 331 349 351 351 351 351 351 
361 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363 363

Non è chiaro (almeno per me) come si possano prevedere i termini futuri. È sicuro affermare che i termini sono sempre dispari, non decrescenti (dopo il secondo termine) e che alcuni numeri vengono ripetuti molte volte.

Sfida

Scrivere un programma o una funzione che prende in un numero intero positivo n e stampe o restituisce il n esimo termine della sequenza SUDSI. Ad esempio, se n è 1, l'uscita è 1, se n è 2, l'uscita è 3, se n è 200, l'uscita è 363.

Prendi l'input in qualsiasi modo normale (stdin / riga di comando / funzione arg). Vince la
risposta più breve in byte .
(Quel sito codifica le cose in UTF-8, ma è possibile utilizzare qualsiasi codifica dannatamente esistente che si desidera.)

Bonus Mathy: (potenzialmente idoneo per la taglia)

  • Dimmi di più sulla sequenza SUDSI. Qual è lo schema sottostante a quali numeri ne fanno parte e quanti di essi ci sono (e cose del genere)? (Non ho trovato SUDSI su OEIS a proposito.)

Come di nuovo Meglio non collegarsi che creare confusione sulla codifica.
Ottimizzatore

@Optimizer Mi collego a quel contatore di byte con lo stesso fraseggio da anni . Perché improvvisamente causerebbe più confusione di quanto abbia mai fatto?
Hobby di Calvin il

1
@orlp Immagino che sarebbe una bella caratteristica aggiuntiva , ma mi affido personalmente alla possibilità di copiare e incollare poiché raramente ho file di origine per i miei invii.
Martin Ender,

1
@orlp Ma chi ne avrà bisogno comunque? Possono vedere le dimensioni direttamente se avessero il file. E non è così facile rimuovere la nuova riga alla fine in alcuni sistemi operativi.
jimmy23013,

2
orlp

Risposte:


5

Pyth, 45 41 40 38 byte

MXGH_HhugGm@Gtd,s<>GH2.a-@GH@GhHtQr1yQ

Ho notato (come ha fatto Martin Büttner) che il numero massimo interessato di una fase di permutazione kè 2k + 1. Ma dal momento che abbiamo solo dei n - 1passaggi, abbiamo solo bisogno di un elenco dei numeri fino a 2n - 1.

Provalo online: dimostrazione

M                       define a function g(G, H): return
                        (G is the list of numbers, H is a tuple)
 XGH_H                     a translation of G
                           (replaces the elements in H with the elements in reversed H)
                           in this application it swaps two values in the list G


                        implicit: Q = input()
 u     tQr1yQ           reduce, G = [1, 2, ..., 2*Q-1]
                        for each H in [0, 1, ..., Q - 2]:
                           G = 
  gG...                        g(G, ...)
h                       print the first element of the resulting list

And the second argument ... of the function call g is:

     ,                  create the tuple (
      s<>GH2               sum(G[H:][:2]), 
            .a-@GH@GhH     abs(G[H],G[H+1])
                        )
m@Gtd                   and map each value d to G[d - 1]

Esiste una sanzione per l'utilizzo di Pyth al di fuori di una libreria?
Alex A.

1
@Alex A. Haha, no. Ma ce n'è uno per non restituire libri.
Jakube,

18

Mathematica, 88 byte

Last[f@n_:=n;(r=f@1;{f@a,f@b}={f[b=+##],f[a=Abs[#-#2]]};r)&@@f/@{#,#+1}&/@Range@Input[]]

Questo è un programma completo, che legge l'input da un prompt. È un'implementazione molto diretta della definizione, in cui tengo traccia della sequenza corrente in f(i cui valori sono f[n]predefiniti in n).

Ecco una versione leggermente più leggibile:

Last[
  f@n_ := n;
  (
    r = f@1;
    {f@a,f@b} = {f[b=+##],f[a=Abs[#-#2]]};
    r
  ) & @@ f /@ {#,#+1} & /@ Range @ Input[]
]

Qualche analisi

Ho tracciato i primi 2000 elementi della sequenza (in seguito non diventa più interessante):

inserisci qui la descrizione dell'immagine

Quindi la sequenza è essenzialmente lineare con la pendenza 2 e presenta sempre alcuni di questi passaggi. Sembra che i passaggi crescano in modo sublineare (se non sono nemmeno delimitati), poiché diventano appena percettibili quando si aumenta il numero di punti tracciati.

Possiamo giustificare la crescita lineare abbastanza facilmente (questo è un po 'ondulato, ma penso che reggerebbe a una prova rigorosa per induzione): inizialmente, il numero massimo interessato di una fase di permutazione nè n + (n+1) = 2n + 1. Si noti inoltre che questi numeri verranno sempre spostati 1, poiché |n - (n+1)| = 1. Quindi non sorprende che otteniamo numeri approssimativamente 2nnella sequenza. Tuttavia, possiamo anche notare che per i passaggi fino a n , S n + 1 è sempre delimitato da n + 1 , il che significa che nessun passaggio di scambio può scambiare due numeri che sono entrambi maggiori di n . Pertanto, i numeri che devono ancora essere elaborati saranno inferiori o uguali al loro valore iniziale. Quindi,2n + 1 è anche il limite per la sequenza stessa.

Penso che trovare un argomento per la lunghezza dei passaggi sarà più complicato.


3
+1 per una buona soluzione ma soprattutto per l'analisi molto interessante e istruttiva!
Alex A.

4

CJam, 45 40 39 byte

Solo un approccio ingenuo. Può essere ulteriormente giocato a golf. Manca troppo una funzione di scambio di array.

ri_K*,\{\:L>2<L1$:+:S@:-z:DL=tDSL=t}/1=

Come funziona:

ri_                             "Read the input, convert to integer and copy it";
   K*,                          "Multiply the copy by 20 and get 0 to 20*input-1 array";
      \{ ... }/1=               "Swap and put input on stack and run the loop that many";
                                "times. After the loop, take the second element as";
                                "we have a 0 based array while series is 1 based";
{\:L>2<L1$:+:S@:-z:DL=tDSL=t}
 \:L                            "Swap to put iteration index behind the array";
                                "and store array in L";
    >2<                         "In each loop, the iteration index will be on stack";
                                "Get the two elements from the array starting at that";
       L1$                      "Put the array on stack and copy the tuple";
          :+:S                  "Get the sum and store it in S";
              @:-z:D            "Get the absolute difference of the tuple and store in D";
                    L=t         "Put the element at S diff at sum index";
                       DSL=t    "Put the element at S sum at diff index";

Provalo online qui


4

Haskell, 95 byte

f#n=let b=f$n+1;l=f n+b;r=abs$f n-b;y x|x==l=f r|x==r=f l|1<2=f x in y
p n=foldl(#)id[1..n-1]$1

Esempio di utilizzo: p 70->139

Non memorizzo la sequenza in un elenco o array. Aggiorna ripetutamente la funzione Identity in una funzione con i due elementi del passaggio corrente scambiati. Dopo i npassaggi chiamo la funzione risultante con il parametro 1.


2

J, 63 byte

3 :'{.>((1-~{(+,|@-)]{~1+[)|.@:{`[`]}])&.>/(<"*i.1-y),<>:i.3*y'

Utilizzo e test:

   f=.3 :'{.>((1-~{(+,|@-)]{~1+[)|.@:{`[`]}])&.>/(<"*i.1-y),<>:i.3*y'

   f 5
9
   f every 1+i.20
1 3 1 7 9 11 11 11 15 15 19 19 19 19 19 19 19 19 19 19

Provalo online qui.


1

Pyth, 55 53 51

Probabilmente può essere ulteriormente giocato a golf. Potrebbe essere molto lento in generale nperché ero pigro per capire quanto tempo avrei avuto bisogno di un array e ne ho usato n^nuno.

Grazie a Volatility e Martin Büttner per aver sottolineato che posso usare un massimo di 3n.

KU*3QFNr1QJ@KN=G@tKNAJG,+JG.a-JG=Y@KJ XXKJ@KGGY)@K1

Spiegazione

                   Q = input (implicit)
KU*3Q              K = range(3 * Q)
FNr1Q              for N in range(1, Q):
 J@KN               J = K[N]
 =G@tKN             G = K[1:][N]
 AJG,+JG.a-JG       J, G = J + G, abs(J - G)
 =Y@KJ              Y = K[J]
 XXKJ@KGGY          K[J], K[G] = K[G], Y
)
@K1                print K[1]

Ho eseguito alcuni test e sembra che la lunghezza dell'elenco richiesta converga in 2*nper grande n, con un massimo di 3*nper n=1.
Volatilità

@Volatility In sostanza, il massimo è 2n+1, che come dici tu ha il massimo a 3per n=1e (in un senso) converge a 2n. Questo non è troppo sorprendente dal momento che è il massimo per la sequenza non permutata, e nessun passo nel processo può aumentare un numero che è ancora avanti. Potrei aggiungere questo alla mia risposta.
Martin Ender,

Vedo che stai già mettendo la mia .aestensione a buon lavoro! Ci sono molte altre chicche in arrivo, ma Isaac sta dormendo proprio ora: github.com/isaacg1/pyth/pull/32
orlp

@orlp, in realtà mi è capitato di leggere i documenti mentre scrivevo il codice (di solito uso doc.txtsu GitHub per un manuale) e ho visto l'aggiornamento. Fortunatamente, come avrei potuto semplicemente
saltarlo

1

Python 2, 117 106 101

j=input();a=range(3*j)
for i in range(1,j):b,c=a[i:i+2];d=abs(b-c);a[b+c],a[d]=a[d],a[b+c]
print a[1]

Utilizza una dict(mappa) per salvare i valori per utilizzare indici arbitrari. g(n)è una funzione che restituisce l' nelemento th. Quindi esegue l'iterazione dei input-1tempi e genera il primo elemento.

Si scopre che è più breve usando i metodi della mia risposta Pyth.

Grazie a xnor per aver salvato 5 byte.


È possibile utilizzare l'elenco disimballaggio: b,c=a[i:i+2]. Inoltre, b+cè abbastanza breve che salvarlo in una variabile sperde i caratteri oltre a scriverlo due volte.
xnor

1

Vai a 150

func f(j int){a:=make([]int,j*2);for i:=range a{a[i]=i};for i:=1;i<j;i++{b,c:=a[i],a[i+1];v:=b-c;if v<0{v*=-1};a[b+c],a[v]=a[v],a[b+c]};println(a[1])}

Ungolf, niente di complicato, per lo più rubato da @ Pietu1998

func f(j int) {
    a := make([]int, j*2) // Build the array we will be working on
    for i := range a {
        a[i] = i
    }
    for i := 1; i < j; i++ {
        b, c := a[i], a[i+1]
        v := b - c
        if v < 0 {
            v *= -1
        }
        a[b+c], a[v] = a[v], a[b+c]
    }
    println(a[1])
}

http://play.golang.org/p/IWkT0c4Ev5


1

Java, 162

int f(int n){int a[]=new int[2*n],s,d,x,t;for(x=0;x<2*n;)a[x]=++x;for(x=0;++x<n;){s=a[x]+a[x-1]-1;d=Math.abs(a[x]-a[x-1])-1;t=a[s];a[s]=a[d];a[d]=t;}return a[0];}

Spiegazione

int f(int n) {
    int a[] = new int[2 * n], sum, diff, x, temp;
    for (x = 0; x < 2 * n;) {
        a[x] = ++x;  // set initial array
    }
    for (x = 0; ++x < n;) {
        sum = a[x] + a[x - 1] - 1;
        diff = Math.abs(a[x] - a[x - 1]) - 1;
        temp = a[sum];
        a[sum] = a[diff];
        a[diff] = temp;
    }
    return a[0];
}

È possibile salvare due byte spostando il corpo del secondo ciclo nella clausola di incremento dell'istruzione for. (Separare le dichiarazioni con una virgola anziché con una semicola.)
AJMansfield

1

dc, 134 132 131 byte

[_1*]sOdsn2*ddslsSsa[ladd:S1-dsa0<P]dsPx1d0rsN:N[la1+dsad;SdS@r1+;SdS@rL@L@r+Ss-d0>Od;SrLsdSsrLs;Sr:S:S1;SladsN:Nlaln>G]dsGxln1-;Nf

Usa echo $n $code | dcdove$n è n ed $codeè ... il codice ( sussulto ). Citazione a piacere.

Modifica: A meno che tu non mi assilli per una spiegazione, non ci riuscirò mai.


Devo aggiungere tre byte per `-e`?
Joe,


È stata una conversazione con te stesso?
NoOneIsHere

@NoOneIsHere: Sì, certo che lo era. Era una domanda aperta a chiunque, ma ho trovato la risposta.
Joe

0

Perl 5, 131

Una soluzione ingenua (ovvero un'implementazione diretta della definizione). Una subroutine, accetta input come un elenco di 1s della lunghezza desiderata.

{map$a[$_]=$_,1..3*@_;($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_;$a[1]}

Visualizza il suo output ad es print sub...->(1,1,1,1,1) .

Spiegazione:

map$a[$_]=$_,1..3*@_costruisce l'array @a, indicizzando ogni intero da solo da 1 a 3 volte la dimensione di@_ (l'input).

($a[$a[$_-1]+$a[$_]],$a[abs($a[$_-1]-$a[$_])])=($a[abs($a[$_-1]-$a[$_])],$a[$a[$_-1]+$a[$_]])for 2..@_ripete lo switcheroo ripetutamente (una volta meno della dimensione di @_), passando $a[$a[$_-1]+$a[$_]]da $a[abs($a[$_-1]-$a[$_])]come $_va da 2 alla dimensione di@_ .

E quindi la subroutine ritorna $a[1].


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.