Selbstkürzender Prime Tester

8

Lassen Sie uns gleich loslegen. Ihre Herausforderung besteht darin, ein Programm zu erstellen, das diese Dinge abhängig von seiner Eingabe ausführt:

  1. Wenn die Eingabe eine Zahl ist, geben Sie "Primzahl" aus, wenn die Zahl eine Primzahl ist, und "Nicht Primzahl", wenn die Zahl keine Primzahl ist. Sie können davon ausgehen, dass die Zahl> 1 ist.

  2. Wenn es sich bei der Eingabe um zwei Zahlen handelt, geben Sie jede einzelne Primzahl zwischen der ersten Zahl (einschließlich) und der zweiten Zahl (exklusiv) aus. Sie können davon ausgehen, dass die erste Zahl kleiner als die zweite ist.

  3. Hier kommt die eigentliche Herausforderung: Wenn keine Eingabe erfolgt, sollte das Programm eine kürzere Version von sich selbst ausgeben, die genau die gleichen Aktionen wie das ursprüngliche Programm ausführt. Das Programm darf weder aus Dateien noch aus dem Internet lesen. Das neue Programm sollte dies auch können. Es sollte für mindestens 5 Generationen funktionieren. Das neue Programm muss nicht in derselben Sprache wie das erste sein.

Wertung:

Ihre Punktzahl entspricht der Summe der Anzahl der Bytes in den ersten fünf Generationen Ihrer Übermittlung (die Übermittlung selbst ist die erste Generation). Wenn der neue Code im ersten Programm fest codiert ist, multiplizieren Sie die Punktzahl mit 1,5. Die niedrigste Punktzahl gewinnt. (Wenn Sie einen Fehler im Punktesystem finden, lassen Sie es mich bitte in den Kommentaren wissen.)

Loovjo
quelle
1
Sie sollten Bedingungen für den Quine-Teil angeben: Darf
Level River St
Ich denke, meine Änderungen betreffen alle bis auf einen der vorherigen Kommentare. Das einzige verbleibende Problem: Was zählt als harte Codierung?
Rainbolt
Ich denke, dies ist ein [Code-Golf] ("kürzester Code gewinnt" in einigen Metriken), keine Notwendigkeit, eine [Code-Herausforderung] zu sein.
Kennytm
Wie wäre es mit "Prime Program Generator" , "Produce Five Generations of Primes" oder "Prime Pseudo Quine Generator" ?
Rainbolt

Antworten:

10

CJam, 66 + 65 + 64 + 63 + 62 = 320 325 355 Bytes

Die folgenden 5 Zeilen sind die ersten 5 Generationen:

{     `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{    `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{   `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{  `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~
{ `(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~

Der letzte produziert

{`(\1>+q~](\_,["_~"a{~mp'P"Not p"?"rime"@;}{~,>{mp},p;}]=~}_~

die immer noch die Hauptaufgaben korrekt ausführt.

Testen Sie es hier.

Erläuterung

Das grundlegende CJam Quine ist

{"_~"}_~

die sehr leicht zu einer verallgemeinerten Quine erweitert werden kann. Eine Erklärung hierzu finden Sie in meiner Antwort hier .

Die Grundideen für diese Antwort sind:

  • Beginnen Sie das Quine mit einer Reihe von Leerzeichen und entfernen Sie eines davon beim Quining.
  • Holen Sie sich ein Array mit allen Eingabenummern (0, 1 oder 2) und wählen Sie einen Code aus, der abhängig von der Länge ausgeführt werden soll (indem Sie ihn zum Indizieren in ein Array verwenden).

Hier ist eine Aufschlüsselung des Codes in der Quine:

"Remove a space from the block's string representation:";
`(\1>+
`      "Get the string representation of the block.";
 (\    "Slice off the leading '{' and pull the remaining string back up.";
   1>  "Remove the first character, i.e. a space.";
     + "Prepend the '{' to the string again.";

"Get the array of inputs and choose the code:";
q~](\_,[...]=~
q~             "Read and eval the input.";
  ]            "Wrap everything (including the string for the block) in an array.";
   (\          "Shift off the string and swap it with the rest of the array.";
     _,        "Duplicate the input array and get its length.";
       [...]=  "Use it to index into this array.";
             ~ "If there are no inputs there will now be an array on the top of the
                stack, which ~ will unwrap. Otherwise there will be a block which ~
                will evaluate.";

"If there is no input, push the string needed for the quine and put it in
 an array for ~ to unwrap:";
"_~"a

"If there is one input, test for primality:";
~mp'P"Not p"?"rime"@;
~mp                   "Unwrap the input array and test for primality.";
   'P"Not p"?         "Choose either 'P' or 'Not p' depending on the result.";
             "rime"   "Push the common part of the string.";
                   @; "Pull up the quine string and discard it.";

"If there are two inputs, print an array with all the primes in the range:";
~,>{mp},p;
~          "Unwrap the array leaving N and M on the stack.";
 ,         "Get a range [0 1 .. N-1].";
  >        "Drop the first M elements, giving [M M+1 .. N-1].";
   {mp},   "Filter to keep only the primes.";
        p  "Pretty-print the array.";
         ; "Discard the quine string.";
Martin Ender
quelle
Könnten Sie bitte eine Erklärung hinzufügen?
Loovjo
1
@Loovjo Ja, das werde ich, aber nicht bevor ich mit dem Golfen fertig bin. ;)
Martin Ender
Könnten Sie bitte die Programme in verschiedene Codeblöcke einfügen? Ein bisschen verwirrt mich, als ich es zum ersten Mal las.
Loovjo
@Loovjo stellte klar, dass es 5 Programme sind und fügte eine vollständige Erklärung hinzu
Martin Ender
6

C, Punktzahl: 553 + 552 + 551 + 550 + 549 = 2755,

Ursprüngliche Länge: 553, Durchschnitt: 551

EDIT: Nur 5 Generationen, nicht 6!

Es sieht so aus, als hätte Martin mich sowohl in der Zeit als auch in der Punktzahl geschlagen (um fast eine Größenordnung!). Ah, gut.

Das ursprüngliche Programm lautet wie folgt:

char*c="char*c=%c%s%c;k=%d,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%cv);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?%cPrime%c:%cNot prime%c);if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf(%c%cd %c,a);}";k=10000,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%v);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?"Prime":"Not prime");if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf("%d ",a);}

Ich werde es zum besseren Verständnis ein wenig entschlüsseln, aber damit es richtig funktioniert, sind die neuen Zeilen NICHT Teil des Programms.

char*c="char*c=%c%s%c;k=%d,a;p(c,v,d){for(v=2;v<c;v++)d+=!(c%cv);return!d;}int main(int C,char**V){if(C==1){printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);return 0;}a=atoi(V[1]);if(C==2)printf(p(a,0,0)?%cPrime%c:%cNot prime%c);if(C==3)for(;a<atoi(V[2]);a++)if(p(a,0,0))printf(%c%cd %c,a);}";
k=10000,a;
p(c,v,d){
    for(v=2;v<c;v++)
        d+=!(c%v);
    return!d;
}
int main(int C,char**V){
    if(C==1){
        printf(c,34,c,34,k/10,37,34,34,34,34,34,37,34);
        return 0;
    }
    a=atoi(V[1]);
    if(C==2)
        printf(p(a,0,0)?"Prime":"Not prime");
    if(C==3)
        for(;a<atoi(V[2]);a++)
            if(p(a,0,0))
                printf("%d ",a);
}

Das einzige, was sich von Programm zu Programm ändert, ist der Wert von k, der bei jeder Iteration genau eine Ziffer verliert. Interessanterweise wird k nach der 5. Generation Null und bleibt dort, sodass Sie ad infinitum iterieren und immer eine gültige Ausgabe haben können.

BrainSteel
quelle
2

Tcl 253 + 252 + 251 + 250 + 249 = 1255 Bytes

eval [set x {     proc q a\ b {incr b;expr $a%$b?\[q $a $b]:$a==$b}
proc 1 a {if [q $a 1] puts\ Prime {puts Not\ Prime}}
proc 2 a\ b {while $b-\$a {if [q $a 1] puts\ $a;incr a}}
proc 0 {} {puts "eval \[set x {[string ra $::x 1 end]}]"}
$argc {*}$argv}]

Der Code muss mit einem Zeilenumbruch enden. Erläuterung:

eval [set x {...}]

Schreiben Sie den Code in x und führen Sie ihn aus.

$argc {*}$argv

Führen Sie den Befehl aus, dessen Name die Argumentlänge ist, und geben Sie die Argumente weiter.

proc q a\ b {incr b;expr $a%$b?\[q $a $b]:$a==$b}

Gibt 1 zurück, wenn a eine Primzahl ist, sonst 0. Verwendet Rekursion; Der zweite Backslash verhindert das Ersetzen von Befehlen durch den Interpreter und aktiviert den von expr(der faul ist).

proc 1 a {if [q $a 1] puts\ Prime {puts Not\ Prime}}
proc 2 a\ b {while $b-\$a {if [q $a 1] puts\ $a;incr a}}

Einfache Umsetzung der Anforderungen.

proc 0 {} {puts "eval \[set x {[string ra $::x 1 end]}]"}

Dies ist die Quine, die jedes Mal von Anfang an ein Leerzeichen entfernt.

Philipp
quelle
"Ihre Punktzahl entspricht der Summe der Anzahl der Bytes in den ersten fünf Generationen Ihrer Übermittlung (die Übermittlung selbst ist die erste Generation)."
Martin Ender