Hole 2 - Prime Quine

9

Znajdź dziurę 1 tutaj .

Zrób quine, która po uruchomieniu wyświetla wiele własnych bloków kodu źródłowego. W rzeczywistości musi wyprowadzić go n razy, gdzie n jest następną liczbą pierwszą.

Myślę, że przykład pokazuje to najlepiej.

[MY QUINE][MY QUINE]
[MY QUINE][MY QUINE][MY QUINE]
[MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE]
[MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE]
[MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE][MY QUINE]

Każdy program wyświetli swój podstawowy „blok” (czyli [MY QUINE]) następną liczbę pierwszą razy.

Wbudowane funkcje do obliczania, czy liczba jest liczbą pierwszą (jak funkcja isPrime) lub do określania następnej liczby pierwszej (jak funkcja nextPrime ()) są niedozwolone.

  • Oznacza to, że funkcje wyliczające liczbę dzielników są niedozwolone
  • Funkcje zwracające pierwszą faktoryzację są również niedozwolone

Powinno to być prawdziwe quine (z wyjątkiem pewnej swobody, patrz następny punkt), więc nie powinieneś czytać własnego kodu źródłowego.

Ponieważ języki takie jak Java i C # są już w niekorzystnej sytuacji, nie musisz generować całkowicie działającego kodu. Jeśli można go wstawić do funkcji (która jest wywoływana) i wypisać następny quine, jesteś dobry.

To jest golf golfowy, więc wygrywa najkrótszy kod!

Stretch Maniac
źródło
Nikt nie odpowiedział na dołek 1, więc jaki wynik otrzymają wszyscy odpowiadający na pierwszy dołek?
Optymalizator
1
Czy możesz wyjaśnić tę część za pomocą głównych funkcji? Czy możemy z nich korzystać, czy nie?
Martin Ender
3
Co uważa się za sprawdzanie liczby pierwszych, a co nie? Biorąc pod uwagę, że sprawdzanie liczby pierwszych można zbudować za pomocą dowolnego quine, jeśli tego rodzaju, zasady nie są wystarczająco jasne
dumny haskeller
@Optimizer: Każdy ma wynik 0 dla pierwszego dołka, dopóki ktoś nie odpowie.
Stretch Maniac
2
@StretchManiac Należy wyraźnie wspomnieć w pytaniu, że zarówno lista głównych metod faktoryzacji, jak i lista metod dzielników są również niedozwolone. Następnym razem opublikuj pytanie w piaskownicy.
Optymalizator

Odpowiedzi:

5

CJam, 31 bajtów

{'_'~]-3>U):U{)__,1>:*)\%}g*}_~

Wypróbuj online w interpretatorze CJam .

Pomysł

Aby sprawdzić prymat, użyjemy twierdzenia Wilsona , które stwierdza, że ​​liczba całkowita n> 1 jest liczbą pierwszą wtedy i tylko wtedy, gdy (n - 1)! ≡ -1 (mod n) , co jest prawdą wtedy i tylko wtedy, gdy (n - 1)! + 1% n == 0 .

Kod

{                           }_~ e# Define a block and execute a copy.
                                e# The original block will be on top of the stack.
 '_'~]                          e# Push those characters and wrap the stack in an array.
      -3>                       e# Keep only the last three elements (QUINE).
         U):U                   e# Increment U (initially 0).
             {           }g     e# Do-while loop:
              )__               e# Increment the integer I on the stack (initially U).
                 ,1>            e#   Push [1 ... I-1].
                    :*          e#   Multiply all to push factorial(I-1).
                      )\%       e#   Push factorial(I-1) + 1 % I.
                                e# While the result is non-zero, repeat.
                                e# This pushes the next prime after U.
                           *    e# Repeat QUINE that many times.
Dennis
źródło
Jak znalazłeś tę metodę sprawdzania liczby pierwszych oO
Optimizer
3
Zapamiętane byłyby dokładniejsze. Jest znany jako twierdzenie Wilsona.
Dennis
mp(czy liczba pierwsza?) istnieje już teraz, więc w najnowszej wersji CJam można trochę bardziej pograć w golfa.
Lynn
1
@Mauris Istniała w pierwszej publicznej wersji, IIRC. Pytanie to zabrania jednak wbudowywania operatorów pierwszych i faktoryzacji.
Dennis
1

CJam, 36 35 bajtów

{]W="_~"]U):U{)_,{)1$\%!},,2>}g*}_~

Można to zdecydowanie pograć w golfa dalej.

Jak to działa:

{                               }_~   "Copy this code block and execute the copy";
 ]W=                                  "Take just the last element from the stack";
                                      "The other thing on stack is the block from above";
    "_~"]                             "Put "_~" on stack and wrap the 2 things in an array";
                                      "At this point, the string representation of stack"
                                      "elements is identical to the source code";
         U):U                         "Increment U and update U's value. This  variable"
                                      "actually counts the number of [Quine] blocks";
             {)_,{)1$\%!},,2>}g       "Find the next prime number"
                               *      "Repeat the array that many times, thus repeat the"
                                      "[Quine] block, the next prime times";

Dzięki Martinowi za przypomnienie mi ]W=sztuczki :)

Wypróbuj online tutaj

Optymalizator
źródło
1

Mathematica, 248 222 bajtów

Edycja: Naprawiono użycie funkcji związanej z liczbą pierwszą, ale także nieco poprawiono quining.

Edycja: Podziękowania dla Dennisa za zapoznanie mnie z twierdzeniem Wilsona.

1;n=If[ValueQ@n,n+1,1];StringJoin@Array[#<>ToString[1##,InputForm]<>#2&@@\("1;n=If[ValueQ@n,n+1,1];StringJoin@Array[#<>ToString[1##,InputForm]<>#\2&@@("*"&,For[i=n,Mod[++i!/i+1,i]>0,0];i]")&,For[i=n,Mod[++i!/i+1,i]>0,0];i]

Zakłada się, że jądro jest zamykane pomiędzy kolejnymi uruchomieniami quine (lub przynajmniej njest resetowane), ponieważ opiera się na nniezdefiniowaniu przed uruchomieniem pierwszego wystąpienia [MyQuine].

Prawdopodobnie można to znacznie skrócić, ale nie mam dużego doświadczenia z quinesami, szczególnie w Mathematica.

Oto wyjaśnienie:

1;

To nic nie robi, ale jeśli połączone na końcu poprzedniej quine, mnoży wynik ostatniego wyrażenia przez 1(co jest brakiem operacji), a średnik tłumi wyjście. To gwarantuje, że tylko ostatnia kopia [MyQuine]drukuje cokolwiek.

n=If[ValueQ@n,n+1,1];

Inicjuje nto 1w pierwszej kopii, [MyQuine]a następnie zwiększa ją o 1każdą kolejną kopię - tzn. Liczy się tylko, ile kopii tam jest n.

Przejdź teraz do końca:

For[i=n,Mod[++i!/i+1,i]>0,0];i

Znajduje następną liczbę pierwszą przy użyciu twierdzenia Wilsona .

StringJoin@Array[#<>ToString[1##,InputForm]<>#2&@@\("QUINE_PREFIX"*"QUINE_SUFFIX")&,NEXTPRIME[n]]

To jest prawdziwy quine. Tworzy NextPrime@nkopie samego kodu. To również trochę dziwne. Tak, mnożę tam dwa ciągi i nie, to nie ma znaczącego wyniku. QUINE_PREFIXzawiera cały kod przed dwoma ciągami i QUINE_SUFFIXzawiera cały kod po dwóch ciągach. Teraz zwykle używasz Apply(lub @@), aby zamienić listę w szereg argumentów. Ale można zastąpić dowolny Headz Apply- np mnożenia. Pomimo tego, że jest to produkt, nadal mogę przekształcić go w dwa argumenty mojej funkcji. Ta funkcja:

#<>ToString[1##,InputForm]<>#2

Gdzie #jest pierwszy argument (ciąg prefiksu), #2jest drugim argumentem (ciąg sufiksu), ##jest sekwencją obu argumentów. Muszę przygotować się 1na zachowanie mnożenia - w przeciwnym ##razie przelałbym się na listę argumentów do ToString. W każdym razie ToString[1##,InputForm]&@@("abc"*"def")zwraca "abc"*"def"... tylko to, czego potrzebuję!

Myślę, że przy wszystkich rzeczach, których potrzebuję wokół quinu, evalbardziej odpowiedni byłby tu oparty na nim quine. Zajmę się tym później lub jutro.

Martin Ender
źródło
@ MartinBüttner pytanie powinno zostać zredagowane
dumny haskeller
Heh, mogę też użyć Twierdzenia Wilsona, aby mój wpis był na równi z Denisem;)
Optimizer,
@Optimizer Ale w moim przypadku nie było niebezpieczeństwa urazienia kogokolwiek, ponieważ nadal używam 7 razy więcej bajtów niż wasza dwójka;)
Martin Ender
@ MartinBüttner Wiem: D Dlatego go nie użyłem :)
Optymalizator
0

J - 60 znaków

Używa metody następnej pierwszej, podobnie jak innych odpowiedzi. (To jest 4 p:trochę.)

((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''

Urocza mała sztuczka J polega na tym f :g, że fgdy podaje się jeden argument, a ggdy podaje się dwa. Więc jeśli napiszesz, powiedz, że f :;'a'f :;'a'f :;'a'to działa jak f'a';'a';'a', co jest świetne, ponieważ jest to lista w ramce, której elementy są 'a'i których długość jest liczbą wystąpień.

Możemy więc podnieść to do quiney. Używany przez fnas wygląd wygląda tak (foo $~ bar), że fookonstruuje część łańcucha, którą powtarzamy w kółko, barznajduje następną liczbę pierwszą i mnoży ją przez 60, czyli długość łańcucha foo.

   ((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
   # ((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
180
   ((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
   # ((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''((58&$,2#{:)@;$~60*4 p:#) :;'((58&$,2#{:)@;$~60*4 p:#) :;'''
300
algorytmshark
źródło
Czy możesz zmodyfikować kod, aby spełniał nowe specyfikacje? Metody generujące następną liczbę pierwszą są niedozwolone. Dzięki.
Stretch Maniac
0

Python 2.7, 214

from sys import*;R,s=range,chr(35)
def N(n):
 if n<3:return n+1
 for p in R(n+1,n+n):
    for i in R(2, p):
     if p%i==0:break
     else:return p
P=file(argv[0]).read();print(P.split(s)[0]+s)*N(P.count(chr(37)));exit(0)
#
dieter
źródło