Genera la sequenza Figura-Figura di Hofstadter


16

A Gödel, Escher, Bach , Douglas Hofstadter introduce una sequenza intera che viene comunemente definita sequenza figura-figura:

2, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, ...

Puoi divertirti a elaborare tu stesso la definizione della sequenza come parte della sfida, ma se non puoi o non vuoi capirla, puoi trovarla su OEIS come sequenza A030124 e una definizione leggermente più chiara su Wikipedia .

Scrivi un programma o una funzione che, dato ntramite STDIN, ARGV o argomento della funzione, stampa un elenco dei primi nnumeri della sequenza su STDOUT in qualsiasi formato di elenco ragionevole.

Questo è il codice golf, la soluzione più breve in byte vince.

Risposte:


6

CJam, 38 30 29 21 byte

li_3*,2>\{(_pX+:X-}*;

Provalo online.

Come funziona

li                     " Read an integer N from STDIN.              ";
  _3*,2>               " Push S := [ 2 3 ... (N * 3 - 1) ].         ";
        \{        }*   " Do the following N times:                  ";
          (            " Shift an integer I from S.                 ";
           _p          " Print a copy of I, followed by a linefeed. ";
             X+:X      " Execute X += I. (X is initialized to 1.)   ";
                 -     " Remove X from S.                           ";
                    ;  " Discard S from the stack.                  ";

Esempio di esecuzione

$ cjam <(echo 'li_3*,2>\{(_pX+:X-}*;') <<< 20
2
4
5
6
8
9
10
11
13
14
15
16
17
19
20
21
22
23
24
25

Hai perso l's di aditsu durante la digitazione dell'URL per l'interprete
Decadimento beta

@BetaDecay quindi perché non modificarlo per risolverlo;)
Martin Ender,

@Martin Non pensavo di avere abbastanza rep ...
Decadimento beta

2
@BetaDecay No, ma puoi comunque suggerirli (che ti dà anche 2 rep se sono accettati).
Martin Ender,

Mi sono sentito così intelligente per giocare a golf con 8 byte aggiuntivi del mio codice. Poi mi sono reso conto che ora fa esattamente lo stesso delle risposte di istocratico, matsjoyce e Peter Taylor ...
Dennis,

6

Haskell, 67 61 60 56 55 53 caratteri

g n=take n$2:4:h
a#(x:s)=[a..x-2]++x#s
h=5#scanl(+)8h

torna al primo algoritmo.

questa soluzione calcola la sequenza del complemento sommando gli elementi iniziali della sequenza. calcola quindi la sequenza come tutti i numeri tra i numeri di sequenza del complemento.

(#)è la funzione che calcola i numeri tra la sequenza del complemento.
hè la sequenza stessa.
gè la funzione che risponde alla domanda.

la funzione g è definita per prendere solo la quantità necessaria di elementi da h.

sottigliezze:

hè in realtà la sequenza di figure, ad eccezione dei primi 2 elementi.
non viene calcolata la sequenza del complemento, ma la sequenza del complemento con l'aggiunta di 1 per ciascun elemento.
queste due sottigliezze sono la ragione scanl(+)8h(che è il codice per la sequenza del complemento (ad eccezione dei primi 2 elementi) con 1 aggiunto) 8. è per il terzo elemento della sequenza del complemento con 1 aggiunto ad esso.
il motivo per cui al calcolo non mancano i primi due elementi è perché vengono aggiunti gin 2:4:h.

esempio:

>g 50
[2,4,5,6,8,9,10,11,13,14,15,16,17,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,57,58,59]

5

Ruby, 54 48

f=->n{x=1
b=*2..n*n
n.times{b-=[x+=p(b.shift)]}}

dimostrazione

Modifica: ho risolto il problema un po 'di più quando mi sono reso conto che non ho bisogno di tenere in memoria l'intera sequenza del complemento. Ecco come funziona ora: usiamo xper tenere traccia del più grande numero calcolato nella sequenza del complemento, ed bè un pool di candidati per la sequenza. nvolte, produciamo il più piccolo elemento rimanente be lo aggiungiamo xper calcolare il numero successivo nella sequenza del complemento. Quindi rimuoviamo entrambi i numeri dal pool di candidati, quindi produciamo sempre il numero più piccolo che non è già stato aggiunto a nessuna delle due sequenze.

Trucchi golf ruby: la sintassi lambda Stabby è più breve di una definizione di metodo. Il requisito che l'output sia dato a STDOUT invece che come valore di ritorno mi ha ispirato a usare il fatto che il valore di ritorno p(x)è x, cosa che normalmente non ricordo perché non è il caso nella versione Ruby usata in Anarchy Golf.


1
Come funziona?
orgoglioso haskeller il

1
FWIW che potresti usare 2..2*n. Devo usarlo n*nperché lo sto facendo in b = [x]^bmodo efficace, quindi ho bisogno che l'elemento più grande bsia più grande del valore più grande di x, ma il tuo b -= [x]richiede solo che bcontenga il valore più grande possibile della sequenza di output.
Peter Taylor,

4

GolfScript ( 24 21 byte)

~.3*,1>\{(\(.p@+\|}*;

Demo online

Ciò è iniziato in modo piuttosto diverso, ma alla fine è converto su una porta GolfScript della soluzione Ruby dell'istocrate prima che Dennis formulasse alcuni suggerimenti che la portassero in una direzione leggermente diversa. In particolare, stampare i numeri man mano che li identifichiamo consente di risparmiare un po 'più di raccoglierli in un array per la stampa alla fine; la ragione è che significa che non dobbiamo mai preoccuparci di più di 3 oggetti in pila.

Dissezione

~.3*,           # Eval input n, dup, multiply by 3, make list [0 1 ... 3n-1]
1>              # Discard 0, which is part of neither sequence
\{              # Execute n times: stack contains pool of numbers not yet seen
                # in either sequence and the first element of it is the next element of the
                # complement sequence
  (\(           #   Pop two numbers from the start of the pool: stack is
                #     pool[0] pool[2..max] pool[1]
  .p            #   Print pool[1]
  @+            #   Rotate pool[0] to top and add to pool[1]
  \|            #   Place pool[0]+pool[1] at the start of the pool and
                #   (this is the clever bit) remove it from later in the pool
}*
;               # Discard the unused remainder of the pool

Se si sostituisce ^con \-, è possibile sostituire ).*con 3*. Ciò non salverà alcun byte, ma riduce drasticamente il tempo di esecuzione e l'utilizzo della memoria. - Dovresti essere in grado di salvare un byte mantenendo l'intero nella parte superiore dell'array. Il loop avrà lo stesso numero di byte, ma l'inizializzazione sarà più corta di un byte.
Dennis,

2
Set union funziona anche meglio della differenza:~.3*,1>\{(\(.p@+\|}*;
Dennis,

3

J - 28 caratteri

Funzione che assume ncome argomento.

($+/\(-.~2+i.)&:>:+/)^:_&2 4

Eseguiamo una funzione, ncome argomento sinistro, sul suo argomento destro ripetutamente fino a quando non produce alcun cambiamento. L'argomento da avviare è l'elenco 2 4.

Nella stessa funzione, prendiamo le somme parziali +/\e la somma completa +/, quindi le incrementiamo entrambe &:>:. Quindi generiamo ogni numero intero da 2 a uno in più della somma totale ( 2+i.) e impostiamo sottrarre ( -.) le somme parziali, lasciando una sequenza figura-figura più lunga per definizione. Infine, abbreviamo o estendiamo ciclicamente l'elenco alla lunghezza n.

Il risultato è che 2 4diventa 3 7, e questo viene rimosso dalla 2..8partenza 2 4 5 6 8. Dopo un altro giro, 2 4 5 6 8diventa 3 7 12 18 26diventa

2 4 5 6 8 9 10 11 13 14 15 16 17 19 20 21 22 23 24 25 27

In questo modo, estendiamo ripetutamente la sequenza figura-figura. Il $comportamento della lunghezza è solo un carattere non banale che consente di risparmiare il modo di attendere che la sequenza cresca di lunghezza no maggiore e di produrre i nprimi valori quando smettono di cambiare. Non dobbiamo nemmeno aspettare molto a lungo: possiamo ottenere fino a 46336 termini da quattro applicazioni del verbo interiore.

La stessa funzione in k:

  • k2, 37 caratteri: {{x#y@&~_lin[y:1+!1+/y;1+\y]}[x]/2 4}
  • k4, 36 caratteri: {{x#y@&~(y:2+!1+/y)in\:1+\y}[x]/2 4}

2

Java - 183 158

Questo è stato il massimo che abbia mai giocato a golf e ne sono orgoglioso! (Anche se non è vicino alla cima delle classifiche (perché è Java))

Grazie a Peter Taylor per i suggerimenti

class f{public static void main(String[]a){int q=1,m=Byte.valueOf(a[0]),w=2,n[]=new int[m*m*2];for(n[q+=w]=1;m-->0;){System.out.println(w);for(;n[++w]>0;);}}}

più grande -

public class f {
    public static void main(String[] a) {
        int q = 1, m = Byte.valueOf(a[0]), w = 2, n[] = new int[m * m * 2];
        for (n[q += w] = 1; m-- > 0;) {
            System.out.println(w);
            for (; n[++w] > 0;)
                ;
        }
    }
}

Quel ciclo interno è incredibilmente offuscato, ma penso che tu possa risparmiare qualche byte. Byte.valueOfsalva tre, e poiché la domanda non specifica l'intervallo di input penso che dovrebbe essere accettabile. Al di fuori dei loop, mviene utilizzato solo per inizializzare n, quindi k++<mpotrebbe essere m-->0, eliminando del ktutto. int[] npuò essere inizializzato come int n[]e unito all'inizializzatore precedente. nnon detiene mai valori diversi da 1, quindi n[...]!=0potrebbe essere n[...]>0. L'inizializzatore può quindi diventare la parte inizializzatore del primo forloop.
Peter Taylor,

E se ti sbarazzi di ue semplicemente usi ++w, non è necessario impostare n[q]o n[w]. C'è un bug, nel senso che scappi alla fine di nquando m==2, che sembra essere risolto meglio inizializzando n=new int[2*m*m], ma penso che sia sceso a 157 byte.
Peter Taylor,

Ciò che intendevo sul fatto che l'inizializzatore diventasse la parte dell'inizializzatore del primo per il ciclo era il for(int q=1,w=2,m=...,n[]=...;m-->0;){...salvataggio di un punto e virgola.
Peter Taylor,

1

Python 2 - 77 byte


Codice:

n=input();x=1;b=range(2,n*n)
while n:v=b.pop(0);x+=v;print v;b.remove(x);n-=1

Funziona allo stesso modo della soluzione di @ histocrat, tranne per il fatto che l'input proviene da stdin.


1

Python 2 - 68

R=[1]
s=0
n=input()
while n:s+=1+(s+1in R);R+=[R[-1]+s];print s;n-=1

0

Gelatina , 15 byte

SƤŻ‘µṀ‘Rḟ
2dz¡ḣ

Provalo online!

Errore di memoria all'ingresso di 6.

Come funziona

SƤŻ‘µṀ‘Rḟ  Aux. link (monad). Input: part of the desired sequence
SƤŻ‘       Sum of prefixes, then prepend a zero and increment
           This is a list of numbers to exclude from the next iteration
    µ      Re-focus on the above
     Ṁ‘Rḟ  Create range 1..Max + 1, then remove all elements of the above
           +1 is needed to progress from [2] to [2,4]

2dz¡ḣ  Main link (monad). Input: n, number of terms
2dz¡   Starting from 2, apply aux. link n times
    ḣ  Take n elements from the beginning

Versione più efficiente, 16 byte

SƤŻ‘µṀ‘Rḟḣ³
2ÇÐL

Provalo online!

Utilizza un'idea da questa risposta J . Troncare alla lunghezza desiderata ogni iterazione e prendere il punto di correzione. Ho pensato di usare S(sum) invece di Ṁ‘(max + 1), ma non posso garantirne la correttezza.


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.