Wygeneruj sekwencję figur i figur Hofstadtera

16

W Gödel, Escher, Bach Douglas Hofstadter wprowadza ciąg liczb całkowitych, który jest powszechnie nazywany ciągiem liczbowym:

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

Możesz czerpać przyjemność z samodzielnego definiowania sekwencji jako części wyzwania, ale jeśli nie możesz lub nie chcesz tego rozgryźć , możesz znaleźć ją w OEIS jako sekwencja A030124 i nieco jaśniejsza definicja na Wikipedii .

Napisz program lub funkcję, która podana nprzez STDIN, ARGV lub argument funkcji wypisuje listę pierwszych nliczb sekwencji do STDOUT w dowolnym rozsądnym formacie listy.

To jest golf golf, wygrywa najkrótsze rozwiązanie w bajtach.

Martin Ender
źródło

Odpowiedzi:

6

CJam, 38 30 29 21 bajtów

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

Wypróbuj online.

Jak to działa

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

Przykładowy przebieg

$ 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
Dennis
źródło
Podczas wpisywania adresu URL dla tłumacza spóźniłeś się na brak aditsu
Beta Decay
@BetaDecay to dlaczego nie edytować, aby to naprawić;)
Martin Ender
@Martin Nie sądziłem, że mam wystarczająco dużo rep ...
Rozpad Beta
2
@BetaDecay Nie, ale nadal możesz je zasugerować (co daje nawet 2 powtórzenia, jeśli zostaną zaakceptowane).
Martin Ender
Czułem się tak sprytnie, gdy odłożyłem 8 dodatkowych bajtów mojego kodu. Potem zdałem sobie sprawę, że teraz robi dokładnie to samo, co odpowiedzi histokraty, matsjoyce i Petera Taylora ...
Dennis
6

Haskell, 67 61 60 56 55 53 znaków

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

powrót do pierwszego algorytmu.

to rozwiązanie oblicza sekwencję dopełniacza przez zsumowanie początkowych elementów sekwencji. następnie oblicza sekwencję jako wszystkie liczby między numerami sekwencji dopełniacza.

(#)to funkcja, która oblicza liczby między sekwencją dopełniacza.
hjest samą sekwencją.
gto funkcja, która odpowiada na pytanie.

funkcja g jest zdefiniowana tak, aby pobierała potrzebną ilość elementów z h.

subtelności:

hjest w rzeczywistości sekwencją figur rysunku, z wyjątkiem pierwszych 2 elementów.
nie jest obliczana sekwencja dopełniacza, ale sekwencja dopełniacza z dodanym 1 dla każdego elementu.
te dwie subtelności są powodem scanl(+)8h(który jest kodem sekwencji dopełniacza (z wyjątkiem pierwszych 2 elementów) z dodanymi 1-ami) 8. dotyczy trzeciego elementu sekwencji dopełniacza z dodanym 1.
powodem, dla którego obliczenia nie brakuje dwóch pierwszych elementów, jest to, że zostały one dodane gw 2:4:h.

przykład:

>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]
dumny haskeller
źródło
5

Ruby, 54 48

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

Próbny

Edycja: Grałem w tę grę jeszcze raz, kiedy zdałem sobie sprawę, że nie muszę przechowywać pełnej sekwencji dopełnień w pamięci. Oto, jak to działa teraz: używamy xdo śledzenia największej obliczonej liczby w sekwencji dopełniacza i bjest pulą kandydatów do sekwencji. nrazy wyprowadzamy najmniejszy pozostały element bi dodajemy go, xaby obliczyć następną liczbę w sekwencji dopełniacza. Następnie usuwamy obie liczby z puli kandydatów, więc zawsze wypisujemy najmniejszą liczbę, która nie została jeszcze dodana do żadnej sekwencji.

Ruby golf tricks: Stabby lambda składnia jest krótsza niż definicja metody. Wymóg, że dane wyjściowe są przekazywane do STDOUT zamiast jako wartość zwracana, zainspirował mnie do użycia faktu, że wartość zwracana p(x)to x, czego zwykle nie pamiętam, ponieważ nie jest tak w wersji Ruby używanej w Anarchy Golf.

histocrat
źródło
1
Jak to działa?
dumny haskeller
1
FWIW możesz użyć 2..2*n. Muszę użyć, n*nponieważ robię to skutecznie, b = [x]^bwięc potrzebuję największego elementu, baby był większy niż największa wartość x, ale b -= [x]wystarczy, że bzawiera on największą możliwą wartość sekwencji wyjściowej.
Peter Taylor,
4

GolfScript ( 24 21 bajtów)

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

Demo online

Zaczęło się to zupełnie inaczej, ale ostatecznie zbiegło się na porcie GolfScript rozwiązania Ruby histocrata , zanim Dennis przedstawił kilka sugestii, które zmierzają w nieco innym kierunku. W szczególności wydrukowanie liczb w miarę ich identyfikacji pozwala zaoszczędzić sporo czasu, gromadząc je w tablicy do drukowania na końcu; Powodem jest to, że w żadnym momencie nie musimy się martwić o więcej niż 3 przedmioty na stosie.

Sekcja

~.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
Peter Taylor
źródło
Jeśli zastąpi ^się \-, można zastąpić ).*z 3*. Nie zaoszczędzi to żadnych bajtów, ale drastycznie skraca czas działania i zużycie pamięci. - Powinieneś być w stanie zapisać jeden bajt, trzymając liczbę całkowitą na górze tablicy. Pętla będzie miała tę samą liczbę bajtów, ale inicjalizacja będzie o jeden bajt krótsza.
Dennis,
2
Set union działa nawet lepiej niż różnica:~.3*,1>\{(\(.p@+\|}*;
Dennis
3

J - 28 znaków

Funkcja njako argument.

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

Uruchamiamy funkcję z nlewym argumentem wielokrotnie na prawym argumencie, dopóki nie wywoła żadnej zmiany. Argument na początek to lista 2 4.

W samej funkcji bierzemy sumy częściowe +/\i pełne +/, a następnie zwiększamy je oba za pomocą &:>:. Następnie generujemy każdą liczbę całkowitą od 2 do jednej więcej niż pełna suma (2+i. ) i ustawiamy odejmowanie ( -.) sumy cząstkowe, pozostawiając z definicji dłuższą sekwencję cyfr i liczb. Wreszcie, skracamy lub cyklicznie rozszerzamy listę do długości n.

Rezultat jest taki , który 2 4zostaje 3 7usunięty z 2..8wyjścia 2 4 5 6 8. Po kolejnej rundzie 2 4 5 6 8staje 3 7 12 18 26się

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

W ten sposób wielokrotnie rozszerzamy sekwencję figura-figura. The$ długości jest po prostu nietrywialnym sposobem oszczędzania znaków na czekaniu, aż sekwencja wzrośnie do długości nlub większej, i wysyłaniu npierwszych wartości, gdy przestaną się zmieniać. Nie musimy też długo czekać: możemy uzyskać aż 46336 terminów z czterech aplikacji czasownika wewnętrznego.

Ta sama funkcja w k:

  • k2, 37 znaków: {{x#y@&~_lin[y:1+!1+/y;1+\y]}[x]/2 4}
  • k4, 36 znaków: {{x#y@&~(y:2+!1+/y)in\:1+\y}[x]/2 4}
algorytmshark
źródło
2

Java - 183 158

To była najbardziej gra w golfa i jestem z tego dumny! (Chociaż nie jest nigdzie u góry list przebojów (ponieważ jest to Java))

Podziękowania dla Petera Taylora za sugestie

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

większy -

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;)
                ;
        }
    }
}
Stretch Maniac
źródło
Ta wewnętrzna pętla for jest imponująco zaciemniona, ale myślę, że możesz zaoszczędzić kilka bajtów. Byte.valueOfoszczędza trzy, a ponieważ pytanie nie określa zakresu danych wejściowych, myślę, że powinno być do zaakceptowania. Poza pętlami msłuży tylko do inicjalizacji n, więc k++<mmoże być m-->0, kcałkowicie eliminując . int[] nmożna zainicjować int n[]i połączyć z poprzednim inicjatorem. nnigdy nie przechowuje wartości innych niż 1, n[...]!=0może tak być n[...]>0. Inicjator może następnie stać się częścią inicjalizacyjną pierwszej forpętli.
Peter Taylor
A jeśli pozbędziesz się ui po prostu użyjesz ++w, nie musisz ustawiać n[q]lub n[w]. Jest jeden błąd, w którym uciekasz przed końcem nkiedy m==2, który wydaje się być najlepiej naprawiony przez inicjalizację n=new int[2*m*m], ale myślę, że jest to do 157 bajtów.
Peter Taylor,
Chodziło mi o to, że inicjalizator, który stał się inicjalizującą częścią pierwszej pętli for, for(int q=1,w=2,m=...,n[]=...;m-->0;){...zapisywał średnik.
Peter Taylor,
1

Python 2 - 77 bajtów


Kod:

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

Działa tak samo jak rozwiązanie @ histocrat, tyle że dane wejściowe pochodzą ze standardowego wejścia.

matsjoyce
źródło
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
Falko
źródło
0

Galaretka , 15 bajtów

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

Wypróbuj online!

Błąd pamięci na wejściu 6.

Jak to działa

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

Bardziej wydajna wersja, 16 bajtów

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

Wypróbuj online!

Wykorzystuje pomysł z tym J odpowiedź . Skracaj do żądanej długości każdej iteracji i weź punkt stały. Myślałem o użyciu S(suma) zamiast Ṁ‘(maks. + 1), ale nie mogę zagwarantować jego poprawności.

Bubbler
źródło
12 bajtów .
Erik the Outgolfer