Eine unberührte Welt programmieren

87

Definieren wir ein unberührtes Programm als ein Programm, das selbst keine Fehler aufweist, das jedoch fehlerhaft ist, wenn Sie es ändern, indem Sie zusammenhängende Teilzeichenfolgen mit N Zeichen entfernen 1 <= N < program length.

Zum Beispiel das dreistellige Python 2-Programm

`8`

ist ein unberührtes Programm ( danke, Sp ), da alle Programme, die aus dem Entfernen von Teilzeichenfolgen der Länge 1 resultieren, Fehler verursachen (Syntaxfehler in der Tat, aber jede Art von Fehler reicht aus):

8`
``
`8

und auch alle Programme, die aus dem Entfernen von Teilzeichenfolgen der Länge 2 resultieren, verursachen Fehler:

`
`

Wenn zum Beispiel `8ein fehlerfreies Programm gewesen `8`wäre, wäre es nicht makellos, da alle Ergebnisse der Entfernung der Teilzeichenfolgen fehlerhaft sein müssen.

Ihre Aufgabe bei dieser Herausforderung ist es, das kürzestmögliche unberührte Programm zu schreiben, das keine Eingabe benötigt, sondern eines der folgenden fünf Wörter ausgibt:

world
earth
globe
planet
sphere

Welches Wort Sie wählen, liegt ganz bei Ihnen. Das einzige Wort und eine optionale nachgestellte Zeile sollten auf stdout (oder die nächstgelegene Alternative Ihrer Sprache) gedruckt werden. Das kürzeste Programm in Bytes gewinnt.

Anmerkungen:

  • Ein eigenständiges Programm ist erforderlich, keine Funktion.
  • Die Wörter sind case sensitive; ausgeben Worldoder EARTHist nicht erlaubt.
  • Compiler-Warnungen gelten nicht als Fehler.
  • Die fehlerhaften Unterprogramme können Eingaben oder Ausgaben annehmen oder irgendetwas anderes tun, solange sie immer irgendwann fehlerhaft sind.

Hier ist ein Stack-Snippet, das auflistet, welche Programme bei einem möglicherweise unberührten Programm fehleranfällig sind:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>function go() { var s = $('#i').val(), e = []; for (var i = 1; i < s.length; i++) { for (var j = 0; j <= s.length - i; j++) { e.push(s.substring(0, j) + s.substring(j + i)); } } $('#o').val(e.join('\n---\n')); }</script>Program:<br><textarea id='i' rows='16' cols='80'>`8`</textarea><br><button onclick='go()' type='button'>Go</button><br><br>Programs that should error: (--- separated)<br><textarea id='o' rows='16' cols='80'></textarea><br>

Calvins Hobbys
quelle
1
@geokavel Ja. Das Abfangen der Ausnahme bedeutet, dass es kein Fehler mehr ist.
Calvins Hobbys
33
Doppelt so viele gelöschte Antworten wie nicht gelöschte. Das ist eine Leistung!
DLosc
1
Kann ein Programm seinen eigenen Quellcode lesen?
Shelvacu
2
Wo kann man die Gravegarde der Antworten auf "Close but no Cigar" und ihre Kommentare sehen?
Vi.
1
@Vi. Erhalten Sie 2.000 Wiederholungen, damit Sie gelöschte Beiträge anzeigen können .
ThisSuitIsBlackNot

Antworten:

46

Schiene , 24 Bytes

$'main'    #
 -[world]o/

Ich denke das funktioniert. Und es ist sowohl kurz als auch lesbar (soweit es Rail betrifft).

  • Wenn die entfernte Teilzeichenfolge einen Teil von enthält, erhalten $'main'wir Internal Error: Crash: No 'main' function found.
  • Wenn die entfernte Teilzeichenfolge die enthält #, kann das Programm nicht ordnungsgemäß beendet werden, sodass es immer mit beendet wird Crash: No valid move. Ich glaube, dass es nicht möglich ist, einen Teilstring so zu löschen, dass der Track eine gültige (Endlos-) Schleife bildet.
  • Wenn sich die entfernte Teilzeichenfolge vor der befindet #, wird sie vom Ende der Strecke getrennt, sodass der Zug abstürzt (mit demselben Fehler wie oben).
  • Befindet sich die entfernte Teilzeichenfolge hinter der #, wird auch die Verbindung #zum Ende der Spur (und möglicherweise sogar zum Anfang der Spur vom Einstiegspunkt $) getrennt. Also nochmal der selbe Fehler.

Was das eigentliche Programm betrifft: Jedes Rail-Programm muss einen $'main'(oder eine längere Variante, aber wir spielen hier Golf) als Einstiegspunkt in die Funktion haben, und der Zug $fährt in südöstlicher Richtung. Alles in dieser ersten Zeile kann Teil der Spur sein. Entfernen 'main'der Spur ist also:

$          #
 -[world]o/

Die -und /sind einfach Schienenstücke, die wir brauchen, damit der Zug diese 45 ° -Drehungen macht.

[world]drückt den String worldund odruckt ihn aus. #markiert das Ende der Strecke - die einzige Möglichkeit, ein Rail-Programm sicher zu beenden.

Interessanterweise ist diese Lösung nur möglich, weil Rail den Gleisen erlaubt, durch die mainLinie zu fahren - wenn das nicht möglich #wäre, wäre es nach der ersten neuen Linie und der Code könnte immer auf gekürzt werden

$'main'
 #

Das ist ein gültiges Programm, das nichts tut. (Nicht-Leerzeichen zwischen 'und #würden das nicht beeinflussen.)

Ebenfalls sehr interessant: Wenn ich nur Golf gespieltworld hätte, wäre das Drucken nicht viel kürzer oder einfacher gewesen:

$'main'
 -[world]o#
Martin Ender
quelle
4
Was ist, wenn ich zwischen [und] Zeichen entferne?
Martin Lütke
@ Martinlütke es wird das /vom trennen #.
Martin Ender
2
@ MartinLütke Du könntest nicht nur die Klammern entfernen, da sie nicht zusammenhängend sind.
Calvins Hobbys
Was passiert, wenn der Zeilenumbruch zwischen den beiden Zeilen entfernt wird?
Vi.
1
@Vi. Dadurch wird die Verbindung zum Gleisanfang getrennt $, sodass der Zug sofort abstürzt (Rail erwartet, dass das Gleis südöstlich des Gleises fortgesetzt wird $).
Martin Ender
43

Funktion ( 186 136 Bytes in UTF-16)

╔══════════════╗
║19342823075080╟
║88037380718711║
╚══════════════╝

Dieses Programm druckt "Welt".

Die meisten Teilzeichenfolgen, die Sie daraus entfernen, verhindern, dass es sich um eine vollständige Box handelt, über die sich der Parser beschwert. Die einzigen möglichen Umzüge, die eine komplette Box hinterlassen, sind:

 ╔══════════════╗
|║19342823075080╟  (remove this whole line)
|║88037380718711║
 ╚══════════════╝
 ╔══════════════╗
 ║|19342823075080╟   ← substring starts at | here
 ║|88037380718711║   ← substring ends at | here
 ╚══════════════╝
... ↕ or anything in between these that removes a whole line’s worth ↕ ...
 ╔══════════════╗
 ║19342823075080|╟   ← substring starts at | here
 ║88037380718711|║   ← substring ends at | here
 ╚══════════════╝
 ╔══════════════╗
|║19342823075080╟
 ║88037380718711║  (both lines entirely)
|╚══════════════╝
 ╔══════════════╗
 ║19342823075080╟
|║88037380718711║  (remove this whole line)
|╚══════════════╝

Die meisten davon entfernen das baumelnde Ende oben rechts an der Box, bei dem es sich um den Ausgangsanschluss handelt. Ohne dieses lose Ende ist die Box nur ein Kommentar:

╔══════════════╗
║88037380718711║
╚══════════════╝

Dies ist kein gültiges Programm mehr, da der Parser ein Programm mit genau einer Ausgabe erwartet:

Fehler: Quelldateien enthalten kein Programm (Programm muss eine Ausgabe haben).

Die einzige Möglichkeit, die einen Ausgangsanschluss verlässt, ist die letzte der oben genannten Möglichkeiten.

╔══════════════╗
║19342823075080╟
╚══════════════╝

Diese Nummer codiert jedoch keine gültige Unicode-Zeichenfolge in Funcitons esoterischem UTF-21. Versuchen Sie dies auszuführen, erhalten Sie:

Unbehandelte Ausnahme: System.ArgumentOutOfRangeException: Ein gültiger UTF32-Wert liegt zwischen einschließlich 0x000000 und 0x10ffff und sollte keine Ersatzcodepunktwerte (0x00d800 ~ 0x00dfff) enthalten.

Daher ist dieses Programm makellos.

Timwi
quelle
3
Ich habe das Gefühl, Sie haben Glück beim letzten Fall (nicht, dass es so einfach ist, versehentlich eine gültige Unicode-Sequenz zu erhalten, aber trotzdem ...)
Esolanging Fruit
34

Visual C ++ - 96 95 Bytes

#include<iostream>
#define I(a,b)a<<b
int main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}

Eigenschaften:

  1. int main()Ohne einen Kompilierungsfehler können Sie keinen Teil von entfernen .
  2. Sie können die AT alles Makros Erweiterung nicht entfernen ändern, zu entfernen abei allen Mitteln main()nie bekommt {, das Entfernen büberhaupt bedeutet , dass unsere Linie nicht in einem nicht enden ;, das Entfernen <Mittel std::cout<'w'einen Fehler verursacht und das Entfernen von <<Ursachen std::cout'w', 'w''o'usw.
  3. Sie können keine Parameter aus der Makrodefinition oder dem Makroaufruf entfernen. Die einzigen gültigen Namen für die Definition sind I(a), I(b)die niemals übereinstimmen und Idie zuvor erweitert wurden (. auf der anderen Seite mit I(,Ursachen <<<<und ,)löscht das Semikolon (abgesehen von anderen Fehlern).
  4. Sie können nicht Teil aller entfernen , std::coutohne in eine führenden <<und daher keinesfalls entfernen , #include<iostream>ohne einen Compiler - Fehler am Anfang.
  5. Sie können keinen Teil eines einzelnen Zeichens entfernen, ''haben einen Leerzeichenfehler und 'w,versuchen, alles in ein Zeichen zu verwandeln.
  6. Sie können die linke / rechte Seite eines Makros nicht entfernen, ohne zu viele )oder (auf der anderen Seite zu lassen, z. B. können Sie solche Dinge nicht tun I('w',I('r'.

Kompiliert online mit Visual C ++ .

Auch dies ist kein vollständiger Beweis. Wenn Sie denken, dass Sie es auch ohne Abschnitt zum Laufen bringen können, lassen Sie es mich bitte wissen.

Frühere Versionen verwendeten einen erheblich anderen Ansatz und erwiesen sich als nicht makellos. Deshalb habe ich diese Partituren entfernt.


Nachprüfung:

Das folgende Programm hat bestätigt, dass diese Version mit dem clCompiler von Visual C ++ 2010 fehlerfrei ist. Ich wünschte, ich hätte mir die Mühe gemacht, dies früher zu schreiben:

#include <fstream>
#include <iostream>
char *S = "#include<iostream>\n#define I(a,b)a<<b\nint main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}";
//uncomment to print source code before compile
// #define prints
int main(){
   for(int i=0; i<95; i++)
      for(int j=i; j<95; j++){
         std::fstream fs;
         fs.open ("tmptst.cpp",std::fstream::out);
         for(int k=0; k<95; k++)
         if(k<i || k>j){
            fs << S[k];
            #ifdef prints
               std::cout<<S[k];
            #endif
         }
         fs.close();
         #ifdef prints
            std::cout<<'\n';
         #endif
         //Compile and surpress/pipe all output
         //if it doesn't compile we get a nonzero errorlevel (i.e.true) from system.
         if(!system("cl -nologo tmptst.cpp >x"))
            return 0;
      }
      std::cout<<"PRISTINE!";
}
Linus
quelle
1
Wir stellen fest, dass dies bei diesem Compiler nicht bei allen Compilern der Fall ist.
Joshua
1
Bitte geben Sie ein Beispiel ...
Linus
3
Auf einigen Compilern liefert das leere C ++ - Programm ein Programm, das nichts tut. Abhängig von der Implementierung des iostreams wird möglicherweise auch #include <iostream> kompiliert.
Joshua
5
@Joshua Nur Unterprogramme mit einer Länge von 1 oder höher spielen eine Rolle, daher spielt es keine Rolle, was das leere Programm tut.
ThisSuitIsBlackNot
2
@Comintern, nicht wirklich. Wenn Sie das Kontrollkästchen zum Ausführen der ausführbaren Datei nicht aktivieren, wird die /cOption automatisch einbezogen und kompiliert (als ob Sie eine Bibliothek und kein Programm erstellen würden). Wenn Sie das Kontrollkästchen Ausführen aktivieren, das die Site nicht enthält /c, wird keine Erfolgsmeldung angezeigt. Stattdessen wird der natürliche Eintrag "LINK: Schwerwiegender Fehler LNK1561: Einstiegspunkt muss definiert sein" angezeigt.
Linus
32

Python 3, 79 33

if 5-open(1,'w').write('world'):a

open(1,'w')öffnet die Standardausgabe, dann drucken wir den String. writeGibt die Anzahl der geschriebenen Zeichen zurück. Dies wird verwendet, um das Entfernen von Teilzeichenfolgen zu verhindern: Wenn ein Teil der Zeichenfolge entfernt wird, wird etwas anderes als 5 zurückgegeben, und 5 abzüglich dieses Werts wird dann als true ausgewertet. Aber das führt dazu, dass der if-body ausgeführt wird und aist undefiniert.

Dies basiert auf Anders Kaseorg cleveren unberührten quine hier .

Da nur eine einzige Aussage überprüft werden muss, ist dies viel kürzer als die alte Lösung, aber auch weniger allgemein.

Alte Lösung:

try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r

So stellen Sie sicher, dass es sich wirklich um ein unberührtes Programm handelt:

w=r'''try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r'''
exec(w)
for j in range(1,len(w)):
 for i in range(len(w)+1-j):
  e=w[:i]+w[i+j:]
  try:exec(e,{});print('WORKED',e)
  except:pass

Einige wichtige Punkte:

  • Jede ausgeführte Anweisung kann gelöscht werden. Die Überprüfung der qAusführung erfordert eine Anweisung außerhalb von q. Das trylöst sich schön, indem man mindestens zwei Aussagen benötigt, von denen keine vollständig gelöscht werden kann.
  • Die Überprüfung qder Ausführung erfolgt durch Auswertung ram Ende.
  • Verifizieren , dass qwurde nicht erreicht wird, modifiziert durch eval(q[17:]), was zu bewerten hat Nonefür qgeführt werden.
  • Die ifBedingung ist ein bisschen schwierig, richtig zu machen. Um sicherzustellen, dass es ausgewertet wurde, hat es den netten Nebeneffekt des Einstellens e, der zum Einstellen benötigt wird r. (Dies ist der Grund, warum ich Python 3 verwendet habe, exprda eine Funktion Wunder bei Nebenwirkungen auf Expression-Ebene bewirkt.)
Philipp
quelle
Ist das nicht die Herausforderung, dass kein Entfernen zu einem Syntaxfehler führen würde? Sie scheinen Laufzeitfehler zu provozieren.
Martin Lütke
5
@ MartinLütke Irgendwelche Fehler sind in Ordnung.
Calvins Hobbys
1
Ähm, sind das nicht 79 Bytes?
Der Matt
@TheMatt Ja? Ich habe sie noch einmal gezählt und du scheinst recht zu haben. Vielleicht hat Vergangenheit mich CRLF-Zeilenumbrüche gezählt ... Wie peinlich. Vielen Dank!
Philipp
25

Haskell, 61

x=uncurry(:)
main=putStr$x('w',x('o',x('r',x('l',x('d',[])))))

Jede Art von Fehler ist in Ordnung? In diesem Fall:

Haskell, 39

main=putStr$take 5$(++)"world"undefined
Martin Lütke
quelle
Funktioniert das, wenn Sie einen der Buchstaben entfernen?
Lirtosiast
Es wird während der Ausführung abstürzen. Weil es versuchen wird, undefiniert auszuwerten.
Martin Lütke,
Das ist ausgezeichnet. Faule Bewertung FTW, so scheint es!
DLosc
1
Ich wünschte, 'inits' wäre im Vorspiel :(. Dann: main = putStr $ inits "world" !! 5 (27 bytes)
Martin Lütke
16

JavaScript, 74 73 35 Bytes

if((alert(a="world")?x:a)[4]!="d")x

Es stellte sich heraus, dass die Antwort viel einfacher war als ich dachte ...

Erläuterung

if(
  (
    alert(a="world") // throws a is not defined if '="world"' is removed
        ?x           // throws x is not defined if 'alert' or '(a="world")' is removed
        :a           // throws a is not defined if 'a="world"' or 'a=' is removed
  )
  [4]!="d"           // if "world" is altered fifth character will not be "d"
                     // if 'd' is removed it will compare "world"[4] ("d") with ""
                     // if '[4]' is removed it will compare "world" with "d"
                     // if '(alert(a="world")?x:a)' is removed it will compare [4] with "d"
                     // if '?x:a' is removed [4] on alert result (undefined[4]) will error
                     // if '[4]!="d"' is removed the if will evaluate "world" (true)
                     // if '!', '!="d"' or '(alert...[4]!=' is removed the if will
                     //     evaluate "d" (true)
)x                   // throws x is not defined if reached

// any other combination of removing substrings results in a syntax error
user81655
quelle
Alles entfernen, außer a="world", keine Fehler
anOKsquirrel
3
@anOKsquirrel Es kann nur eine einzige Teilzeichenfolge entfernt werden.
Dennis
4
Ich ging dies wie folgt durch: "Konnte ich das entfernen? Nein, dieser Fehler würde auftreten. Kann das gelöscht werden? Nun, ich denke, es würde diesen anderen Fehler verursachen. Aha! Diese Zeichen können entfernt werden! Oh, warte ..." +1
ETHproductions
if(a="world")["bol"+a[4]]Fehler nicht.
anOKsquirrel
4
Heilige Kuh, es ist jetzt doppelt so beeindruckend! Ich wünschte, ich könnte noch einmal +1 geben ...
ETHproductions
15

Java 8, 301 Bytes

Weil jede Frage eine Java-Antwort braucht.

class C{static{System.out.print(((((w='w')))));System.out.print((((o='o'))));System.out.print(((r='r')));System.out.print((l='l'));System.out.print(d='d');e=(char)((f=1)/((g=8)-C.class.getDeclaredFields()[h=0].getModifiers()));}public static void main(String[]a){}static final char w,o,r,l,d,e,f,g,h;}

Erweitert

class C {
    static {
        System.out.print(((((w = 'w')))));
        System.out.print((((o = 'o'))));
        System.out.print(((r = 'r')));
        System.out.print((l = 'l'));
        System.out.print(d = 'd');
        e = (char) ((f = 1) / ((g = 8) - C.class.getDeclaredFields()[h = 0].getModifiers()));
    }

    public static void main(String[] a) { }

    static final char w, o, r, l, d, e, f, g, h;
}

Erläuterung

  • public static main(String[]a){} ist nötig.
  • Wenn die Felddeklarationen entfernt (oder nicht statisch gemacht) werden, kann der erste statische Block sie nicht finden.
  • Wenn der statische Block entfernt (oder nicht statisch gemacht) wird, werden die Felder nicht initialisiert.

Der schwierigste Teil:

  • Wenn das finalSchlüsselwort entfernt wird, wird die zweite Zeile zu ausgewertet 1/(8-8), was zu einer / by zeroAusnahme führt.
Ypnypn
quelle
Warum können Sie die Innenseiten der Druckanweisungen nicht entfernen?
Nic Hartley
2
@QPaysTaxes Es gibt keine leere System.out.print()Methode. Es gibt für println(), aber nicht für print(). Wenn Sie es entfernen d='d'würden, gäbe es einen The method print(boolean) in the type PrintStream is not applicable for the arguments ()Fehler (und wenn Sie es entfernen d=würden, gäbe es einen The blank final field d may not have been initializedFehler).
Kevin Cruijssen
15

Funktion , 143 142 136 Bytes

Die Bewertung erfolgt wie gewohnt in UTF-8, da UTF-16 (aufgrund der Stückliste) zwei Byte größer wäre.

╔══════════╗
║1934282307║╔╗
║5080880373╟╚╝
║80718711  ║
╚══════════╝

Daher habe ich eine Weile über eine Antwort von Funciton nachgedacht und mir gedacht, dass dies unmöglich ist, da Sie immer eine vollständige Zeile entfernen können und der Code immer noch einen gültigen Block bildet. Dann habe ich mit Timwi darüber gesprochen und er hat herausgefunden, dass man einfach die ganze Zahl in eine einzige Zeile setzen kann, so dass das Entfernen das Programm aufgrund des Fehlens eines Ausgangsanschlusses zum Erliegen bringt .

Literale in einer einzelnen Zeile sind jedoch bekanntermaßen teuer, sowohl wegen der größeren Zeichenanzahl als auch wegen der größeren Anzahl von Nicht-ASCII-Zeichen. Und seine Erwähnung eines "leeren Kommentar" -Blocks brachte mich zum Nachdenken ...

Also habe ich mir eine effizientere Lösung ausgedacht, die einen zusätzlichen leeren Kommentarblock verwendet, der kaputt geht, wenn Sie versuchen, alles zu entfernen, was den wörtlichen Block im Takt belassen würde:

  • Wir können die dritte Zeile möglicherweise nicht entfernen, da wir dann den Ausgangsanschluss entfernen würden.
  • Wenn wir die zweite Zeile entfernen, verliert der Kommentarblock seine Oberkante und bricht ab.

Das lässt zwei Möglichkeiten (danke an Steve für den Hinweis):

  • Entfernen Sie die vierte Zeile. Das lässt beide Boxen in Takt. Wenn jedoch die sich ergebende Ganzzahl 19342823075080880373decodiert wird, würde die entsprechende Zeichenfolge , die den Codepunkt enthalten , 0x18D53Bdie kein gültiges Unicode - Zeichen ist, System.Char.ConvertFromUtf32stürzt mit ein ArgumentOutOfRangeException.
  • Entfernen Sie eine vollständige Linie, beginnend nach der rechten oberen Ecke. Auch hier bleiben beide Felder im Takt, aber die resultierende Ganzzahl 508088037380718711würde zwei ungültige Codepunkte enthalten 0x1B0635und 0x140077zur gleichen Ausnahme führen.

Beachten Sie, dass das Entfernen der zweiten Zeile auch ohne den leeren Kommentarblock zu einem ungültigen Codepunkt führen würde. Der Kommentarblock verhindert jedoch, dass wir eine Zeile innerhalb der zweiten Zeile einfügen, um beispielsweise eine Ganzzahl zu erhalten 193428037380718711, die keinen Fehler verursachen würde.

Martin Ender
quelle
Was passiert, wenn Sie die Teilzeichenfolge entfernen, die mit dem Zeichen nach dem Ausgabe-Connector beginnt und genau eine Zeile später endet? dh Entfernen der mittleren Zeile des Kommentarblocks und der Zeile mit "80718711" im Hauptblock, wobei die Ecken beider Kästchen intakt bleiben.
Steve
@ Steve Ich habe die Antwort geändert, um diesen Fall abzudecken. Nachdem ich mir das etwas genauer angesehen hatte, konnte ich zwei Zeichen / sechs Bytes speichern.
Martin Ender
10

Rubin, 36

eval(*[(s="planet")[$>.write(s)^6]])

Wir weisen s="planet"diese Zeichenfolge zu und schreiben sie dann an STDOUT. Dies gibt die Anzahl der geschriebenen Zeichen zurück. Wir xor das mit 6, so dass wir eine ganze Zahl ungleich Null erhalten, wenn etwas anderes als 6 Zeichen geschrieben wurden. Dann schneiden wir smit diesem Index hinein. Nur das 0. Zeichen von s"p" ist eine gültige Codezeichenfolge (keine Operation). Wir übergeben dies an eval, wobei wir die (*[argument])Syntax verwenden, die nur mit der (argument)Ausnahme äquivalent ist, dass sie außerhalb eines Methodenaufrufs nicht gültig ist.

Programmgesteuert überprüfte Aktualität unter Ruby 1.9.3 und 2.2

Histokrat
quelle
Heiliger Strohsack. Das ist großartig.
klatschen
Was passiert, wenn Sie das entfernen *?
LegionMammal978
Dann übergeben Sie ein Array an eval anstelle eines Strings, der ein ArgumentError ist.
Histokrat
9

C #, 128 118 101 Bytes

Ich dachte daran, die zusammenhängende Teilzeichenfolgenregel zu missbrauchen.

Der Code

class h{static void Main()=>System.Console.Write(new char[1
#if!i
*5]{'w','o','r','l','d'
#endif
});}

Warum es funktioniert

  1. class hund static void Main()sind erforderlich.
  2. Das Entfernen der Zeichen in 'w','o','r','l','d'verursacht einen Fehler, da das Zeichen- Array mit der Länge initialisiert wird 1*5.
  3. Sie können den Inhalt in Main () nicht entfernen, ohne die Regel für zusammenhängende Zeichen zu verletzen, da Teile durch Preprocs getrennt sind. (Siehe unten)

Vor dem Golfen und der Trennung

class h
{
    static void Main() =>
        System.Console.Write(new char[1 * 5]{'w','o','r','l','d'});
}

Bestätigt mit

https://ideone.com/wEdB54

BEARBEITEN:

  • Einige Bytes mit #if !xanstelle von gespeichert #if x #else.
  • Verwendete =>Funk-Syntax. #if!xstatt #if !x. Dank an @JohnBot.
  • Aufgrund der =>Funktionssyntax kann eine zusätzliche Preproc-Bedingung entfernt werden.
Helix Quar
quelle
Hallo Helix! Glaubst du, du könntest erklären, wie und warum deine Antwort ein bisschen besser funktioniert?
isaacg
@isaacg Bearbeitet. Beweis folgen.
Helix Quar
Ich kann es nicht kommen , ohne laufen statican Main.
Johnbot
@ Johnbot Ja. Muss fehlkopiert sein. Fest.
Helix Quar
Sie können , indem sie ein Zeichen speichern Mainein Expression-bodied Funktionselement und 2 mehr durch Entfernen des Leerzeichen vor dem Präprozessor Zustand: class h{static void Main()=>System.Console.Write(new char[1\n#if!l\n*5]{'w','o','r','l','d'\n#if!o\n});\n#endif\n}\n#endif. Das sind 115 nach meiner Zählung.
Johnbot
9

MATLAB, 37 36 33 Bytes

feval(@disp,reshape('world',1,5))

Da ich nicht sicher bin, ob wir auch ans = ausgeben dürfen , musste ich einige Umgehungsmöglichkeiten finden, um die Ausgabe in geeigneter Weise durchzuführen. Die Verwendung von fprintf an sich hat nicht funktioniert, da ich mich einfach geweigert habe, Fehler zu machen, egal was ich versuchte. Die Verwendung von disp an sich war keine Option, da es nur 1 Argument annehmen würde und dieses Argument offensichtlich auch fehlerfrei ausgeführt würde.

Wenn es kein Problem ist, ans = auch in die Ausgabe einzubeziehen, kann MATLAB mit 20 Bytes ausgeführt werden :

reshape('world',1,5)
slvrbld
quelle
Ich muss wirklich mehr über die eingebauten Funktionen lernen (+1) // Wenn Ihr Programm 20
Abr001am 11.11.15
2
Das hängt wirklich davon ab, wie streng die Regeln sind. Sie geben an, dass nur 'world' (+ optionaler abschließender Zeilenumbruch) gedruckt werden soll, dann sind es 33 Bytes.
slvrbld
Ja, wir zählen dies als 33. Vielen Dank für
Ihr
9

> <> , 17 Bytes

e"ooooo7-c0pBhtra

Probieren Sie es online!

Druckt "Erde".

Die einzige Möglichkeit, wie ein ><>Programm ohne Fehler beendet wird, besteht in der Ausführung des ;Zeichens. Dies ist ein Problem, da Sie einfach alle Zeichen davor entfernen können, sodass ;das erste Zeichen ausgeführt wird. Sie können dies umgehen, indem Sie den pBefehl verwenden, um das Programm so zu ändern, dass es ;während der Ausführung einbezogen wird . Sie alle Abschnitte des Codes zu entfernen bewirkt , dass die ;nie Fehler über die ungültigen Anweisungen erzeugt werden verursacht B, hund t, Stapel Unterlauf und Endlosschleifen es schließlich machen über genügend Arbeitsspeicher ausgeführt. Ich musste nur sicherstellen, dass alle Endlosschleifen den Stapel füllten.

Alle Varianten wurden mit diesem Python-Snippet getestet:

code = 'e"ooooo7-c0pBhtra'
count = {"invalid":0, "underflow":0, "memory":0}
for l in range(1, len(code)):
    for x in range(0, len(code)-l+1):
        print(code[:x] + code[x+l:], "\t\t", end='')
        try:
            interp = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,1000):
                interp.move()
            print(len(interp._stack), "< ", end='')
            interp2 = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,2000):
                interp2.move()
            print(len(interp2._stack))
            count["memory"] += 1
        except Exception as e:
            print(e)
            if str(e) == "pop from empty list": count["underflow"] += 1
            else: count["invalid"] += 1
print(count) 
#don't judge me

wurde dem offiziellen fish.py- Interpreter des Erstellers von> <> hinzugefügt (eine leicht modifizierte Version von) . Von 152 möglichen Unterprogrammen sind 92 aufgrund ungültiger Anweisungen fehlerhaft, 18 aufgrund eines Stapelunterlaufs und 42 aufgrund eines Speichermangels.

Witzige Fakten, die erste Version e"ooooo6-c0pAhtrahatte ein paar verrückte Unterprogramme, die es schafften, den Befehl put zu verwenden [, um anstelle der ungültigen Anweisung einen zu platzieren, der den Stack löscht A. "Earth" ist auch die einzige Phrase, die mit dieser Methode funktioniert, da der erste Buchstabe eeine gültige Anweisung in ist ><>. Andernfalls muss der "Befehl an der Vorderseite des Programms platziert werden, und ein gültiges Unterprogramm kann sich "von selbst befinden.

Scherzen
quelle
8

Rubin, 34

eval(*[($>.write("world")-1).chr])

Dies hat einige Komponenten:

eval(*[ expr ]) stammt aus der Antwort von histocrat und ist makellos. Außerdem ist es ein gültiges Ruby-Programm, das keine Fehler verursacht, wenn der Rückgabewert von expr überprüft wird. method(*arr)ist eine Ruby-Syntax, die methodmit den Werten von arrals Argument aufruft . Der Grund, warum dies hier erforderlich ist, ist, dass es nur als Parameter für eine Methode gültig ist, sodass ein Syntaxfehler vorliegt , wenn evales entfernt (*[expr])wird. Wenn expr entfernt wird, wird evalbeanstandet, dass nicht genügend Argumente vorhanden sind

$>.write("world")-1kann nur innerhalb der Zeichenfolge und der Subtraktion entstellt werden. $>.write("world")schreibt "world" nach STDOUT und gibt die Anzahl der geschriebenen Zeichen zurück, subtrahiert dann 1. Daher ist der Wert genau 4, wenn das Programm nicht entstellt ist . Wenn es verstümmelt ist (entweder wird das -1entfernt oder die Zeichenfolge gekürzt), wird eines von -1,0,1,2,3 oder 5 zurückgegeben . Alle anderen Verstümmelungen führen zu einem Syntaxfehler.

Wenn Sie chreine Nummer anrufen, wird das durch diese Nummer dargestellte Zeichen zurückgegeben. Wenn also das Ergebnis des obigen Beispiels aufgerufen wird, tritt ein Fehler bei -1 auf und ansonsten wird eine Zeichenfolge mit einem einzelnen Zeichen zurückgegeben.

Ich bin mir nicht sicher, warum das so ist, aber es scheint, dass Ruby \x04als Leerzeichen interpretiert wird , was bedeutet, dass der Ausdruck gültig ist (leere Ruby-Programme tun nichts). Alle anderen Zeichen ( \x00- \x03und \x05) führen jedoch zu Invalid char '\x01' in expression. Ich fand das, indem ich einfach über mögliche Berechnungen iterierte, die ich mit der zurückgegebenen Zahl machen konnte. Zuvor hatte ich benutzt

$>.write("planet
")*16

Wobei "planet" plus ein Zeilenumbruch 7 Zeichen war, mal 16, um 112 zu erhalten p, die einzige Einbuchstabenfunktion in Ruby, die standardmäßig definiert ist. Wenn keine Argumente angegeben werden, ist dies praktisch ein No-Op


Lobende Erwähnung: $><<"%c"*5%%w(w o r l d)ist sehr nah, aber nicht makellos. Das Entfernen von "%c"*5%Ergebnissen führt zu keinen Fehlern. Mini-Erklärung:

$>ist stdout und <<ist eine aufgerufene Funktion. "%c"*5generiert den Formatstring "%c%c%c%c%c", der dann versucht, %durch ein Array formatiert zu werden ( ): Dies %w(w o r l d)ist eine kürzere Version von ['w','o','r','l','d']. Wenn das Array zu wenige oder zu viele Elemente enthält, sodass sie nicht mit der Formatzeichenfolge übereinstimmen, wird ein Fehler ausgegeben. Die Achillesferse ist das "%c"*5, und %w(w o r l d)kann beide unabhängig voneinander existieren, und $><<braucht nur ein Argument von einem. Es gibt also verschiedene Möglichkeiten, dieses Programm in fehlerfreie Cousins ​​zu zerlegen.


Damit validiert:

s = 'eval(*[($>.write("world")-1).chr])'
puts s.size
(1...s.length).each do |len| #how much to remove
  (0...len).each do |i| #where to remove from
    to_test = s.dup
    to_test.slice!(i,len)
    begin #Feels so backwards; I want it to error and I'm sad when it works.
      eval(to_test)
      puts to_test
      puts "WORKED :("
      exit
    rescue SyntaxError
      #Have to have a separate rescue since syntax errors
      #are not in the same category as most other errors
      #in ruby, and so are not caught by default with 
      #a plain rescue
    rescue
      #this is good
    end
  end
end
Shelvacu
quelle
Eine Erklärung in Anlehnung an die Antwort des Histokraten wäre schön. Es scheint, als ob Sie denselben grundlegenden Ansatz verwenden, aber da ich Ruby nicht kenne, kann ich die Details nicht verstehen.
ThisSuitIsBlackNot
@ThisSuitIsBlackNot Habe ich mein Bestes gegeben, irgendetwas, was du nicht verstehst?
Shelvacu,
Hervorragende Erklärung, danke!
ThisSuitIsBlackNot
6

Python 3 , 43 Bytes

for[]in{5:[]}[open(1,"w").write("world")]:a

Probieren Sie es online!

Wie es funktioniert

Zum Schutz vor Löschungen von Teilzeichenfolgen verwenden wir open(1,"w").writeanstelle von print. Gibt in Python 3 writedie Anzahl der geschriebenen Zeichen zurück, um 5sicherzustellen, dass kein Teil der Zeichenfolge gelöscht wurde. Wir tun dies, indem wir den Rückgabewert im Dictionary {5:[]}nachschlagen und das Ergebnis mit for[]in…:adurchlaufen, was fehlschlägt, wenn wir kein leeres Iterable erhalten haben oder wenn die forAnweisung gelöscht wird.

Anders Kaseorg
quelle
4

Javascript (Node.js), 93 bis 95 Bytes

if(l=arguments.callee.toString().length,l!=158)throw l;console.log("world");if(g=l!=158)throw g

Überprüfen Sie die eigene Größe zweimal, damit bei fehlenden Zeichen ein Fehler ausgegeben wird. Die Länge beträgt 156, da Node.js function (exports, require, module, __filename, __dirname) {dem Code zur Laufzeit vorangestellt wird .

Vielen Dank an Martin Büttner für den Hinweis auf einen Fehler. Jetzt behoben.

Naouak
quelle
4

Perl 5.10+, 71 63 Bytes

(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}

Druck worldmit einem Newline. Laufen Sie wie folgt:

perl -M5.010 file

Dies filehängt von der Byteanzahl des Quellcodes ab und muss daher den obigen Code und nichts anderes enthalten (kein Schebang, kein abschließender Zeilenumbruch). Für sayund den defined-or-Operator wird Perl 5.10+ benötigt //.


Es ist unglaublich schwierig, mit Perl ein makelloses Programm zu erstellen, weil:

  • Jede Bareword Kennung (zB foo, a, _) ist eine gültige Anweisung mit no strict 'subs';(Standardeinstellung). Dies bedeutet, dass das Programm weder mit einem Buchstaben, einer Ziffer oder einem Unterstrich beginnen noch enden kann.

  • Wie tchrist erklärt , "haben über symbolische Dereferenzierung angegebene Bezeichner keinerlei Einschränkung bezüglich ihrer Namen." Das bedeutet , das Programm kann nicht mit einem der sigils beginnen $, @, %, oder *, da alle , aber die erste und letzte Zeichen zu entfernen würde immer einen gültigen Variablennamen verlassen.

  • Viele integrierte Funktionen (einschließlich der meisten Funktionen, die zur Ausgabe in der Lage sind) funktionieren $_standardmäßig, sodass Aufrufe häufig auch dann funktionieren, wenn Sie das Argument entfernen (z . B. say"world"vs. say).

Wie es funktioniert

Diese Lösung wurde von Naouaks Antwort auf Node.j inspiriert , die ihre eigene Länge überprüft, um sicherzustellen, dass Zeichen nicht entfernt wurden.

Das Programm besteht aus zwei Abschnitten, einer in Klammern und der andere in einem Block:

(...);{...}

Der erste Abschnitt liest die Quelldatei und stirbt, wenn sie weniger als 63 Zeichen lang ist. Der zweite Abschnitt prüft, ob die readAusführung erfolgreich war. Wenn einer der Abschnitte entfernt wird (mit oder ohne die umgebenden Klammern oder geschweiften Klammern), löst der andere Abschnitt eine Ausnahme aus.

Wenn Sie die mittlere oder linke oder rechte Seite des Programms entfernen, werden die Klammern und / oder geschweiften Klammern aus dem Gleichgewicht gebracht, was zu einem Syntaxfehler führt.

Wenn die erste diegeändert wird (zu d, e, di, de, oder ie, die alle gültigen Kennungen), die Längenprüfung wird:

@{\(read(0,$a,63)!=63?di:@_)};

was auswertet zu:

@{\'di'};

Dies nimmt einen Verweis auf einen String und versucht, ihn als Array zu dereferenzieren, was zu einem Fehler führt:

Not an ARRAY reference

Wenn eine andere Anweisung geändert wird, schlägt die Längenprüfung fehl und das Programm stirbt.


Mit folgendem Programm verifiziert:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use File::Temp;
use List::MoreUtils qw(uniq);

sub delete_substr {
    my ($str, $offset, $len) = @_;

    my $tmp = $str;
    substr($tmp, $offset, $len) = '';

    return $tmp;
}

sub generate_subprograms {
    my ($source) = @_;

    my $tot_len = length $source;
    my @subprograms;                                             

    foreach my $len (1 .. $tot_len - 1) { 
        foreach my $offset (0 .. $tot_len - $len) {
            push @subprograms, delete_substr($source, $offset, $len);
        }                                                        
    }                                                            

    return uniq @subprograms;                                    
}                                                                

chomp(my $source = <DATA>);                                                                                                       
my $temp = File::Temp->new;                                                                                        

foreach my $subprogram ( generate_subprograms($source) ) {       
    print $temp $subprogram;

    my $ret = system(qq{/usr/bin/perl -M5.010 $temp > /dev/null 2>&1});
    say($subprogram), last if $ret == 0;

    truncate $temp, 0;
    seek $temp, 0, 0;
}

__DATA__
(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}
ThisSuitIsBlackNot
quelle
4

Ruby + Coreutils, 33 27 26 Bytes

`base#{$>.write"world
"}4`

Probieren Sie es online!

Backticks in Ruby führen den darin enthaltenen Befehl aus und geben alles zurück, was das Programm als String in STDOUT geschrieben hat. Die #{expr}Syntax ermöglicht das Einbetten von Ausdrücken in Zeichenfolgen und Backticks. Dieses Programm könnte umgeschrieben werden als:

system("base" + (STDOUT.write("world\n")).to_s + "4")

IO#writeGibt die Anzahl der geschriebenen Bytes zurück. Wenn die Zeichenfolge also gekürzt wird, ist sie nicht die richtige Anzahl. #{}Beim Einbetten wird die Zahl automatisch in eine Zeichenfolge eingefügt. Wenn ein Teil entfernt wird und dies nicht zu einem Syntaxfehler führt, wird der falsche Befehl ausgeführt. Wenn ein Teil von "world"entfernt wird, versucht einer von base04durch base54zu laufen.

Der Zeilenumbruch, egal ob innerhalb oder außerhalb des Strings, ist erforderlich. Andernfalls können die ersten 5 Zeichen ( `base) entfernt werden, wodurch die gesamte Zeile zu einem Kommentar wird. Außerdem müssen ein oder mehrere Zeichen zwischen dem ersten Backtick und stehen #, andernfalls {kann das entfernt werden, um das Ganze zu einem Shell- Kommentar zu machen.


exec(*[(s="ec%co earth")%s[10]])

execErsetzt den aktuellen Ruby-Prozess durch den angegebenen Befehl. Siehe meine andere Antwort für eine Erklärung der meth(*[])Syntax und der Notwendigkeit.

(s="ec%co earth")Weist der Variablen den String "ec% co earth" zu s. Zuweisungen geben das zurück, was zugewiesen wurde, sodass die Zeichenfolge auch zurückgegeben wird.

"format string %d" % 5ist syntaktischer Zucker für sprintf("format string %d",5), jedoch sind Leerzeichen um den %nicht erforderlich.

s[10]Ruft das Zeichen in der Zeichenfolge bei Index 10 ab. Im nicht entstellten Zustand ist dieses Zeichen "h", der letzte Buchstabe in der Zeichenfolge. Das Entfernen von Zeichen in der Zeichenfolge bedeutet jedoch, dass die Zeichenfolge kürzer ist, sodass bei Index 10 kein Zeichen vorhanden ist. s[10]Daher nilwird zurückgegeben und "%c" % nilein Fehler verursacht.

Wenn %s[10]entfernt wird, versucht Ruby, den Befehl auszuführen, der ec%co earthnicht funktioniert.

Das Ändern 10zu 1oder führt 0auch zu einem unbekannten Befehl (entweder eceooder ecco). Das vollständige Entfernen ist technisch gesehen kein Syntaxfehler, da es die Methode #[]für den String aufruft , sich dann aber über nicht genügend Argumente beschwert.


Ein Hinweis zur Lösung dieses Problems im Allgemeinen: Sie benötigen einen Wrapper, der den Code in einem abstrakten Sinne überprüft, während er selbst makellos ist. Zum Beispiel wird ein Programm mit Division am Ende ( blablabla/somevar) niemals funktionieren, da eine Division immer entfernt werden kann ( blablabla). Dies sind einige solcher Wrapper, die ich bisher verwendet habe:

  • eval(*[Code ])von Histokraten und in meiner ersten Antwort verwendet. Überprüft, ob die Ausgabe ein gültiges Ruby-Programm ist
  • exec(*[Der ])oben verwendete Code bestätigt, dass die Antwort ein gültiger Befehl ist
  • `#{ Code }`

Die Backtick-Syntax führt auch einen Befehl aus (und überprüft daher, ob er gültig ist), STDOUT wird jedoch als Zeichenfolge erfasst, anstatt als STDOUT des übergeordneten Prozesses (Ruby's) ausgegeben zu werden. Aus diesem Grund konnte ich es nicht für diese Antwort verwenden. BEARBEITEN: Ich habe es funktionieren lassen. Die oben aufgeführten Einschränkungen.

Edit: Danke an @histocrat für den Hinweis auf einige Mängel

Shelvacu
quelle
Cooler Ansatz! Sie können (und müssen) das Leerzeichen zwischen writeund am Anfang der Zeichenfolge entfernen , aber ich glaube nicht, dass dies die Reinheit beeinträchtigt. Außerdem wird auf meinem Rechner base64auf Eingaben gewartet, was möglicherweise gegen die Regeln verstößt.
Histokrat
@histocrat Wow, ich bin überrascht, dass das $>.write"world"funktioniert, danke! Das Warten auf Eingaben in base64 scheint je nach System zu variieren. TIO funktioniert gut. Das macht es noch unklarer, ob es den Regeln folgt.
Shelvacu
3

PowerShell, (97 Byte + 5 für Programmname) = 102 Byte

"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a

Überprüft sich selbst, bevor es sich selbst zerstört ... zweimal.

Erwartet gespeichert werden c.ps1und aus dem lokalen Verzeichnis als solche ausgeführt:
PS C:\Tools\Scripts\Golfing\> .\c.ps1.

Der Alias gcist eine Abkürzung für Get-Contentund ähnelt dem catLesen einer Datei (in diesem Fall unserem Ausführungspfad .\c.ps1). Wir holen das .Lengthvon der Datei, setzen es auf $aund prüfen, ob es mit 97 nicht gleich ist -eq97. Wenn es gleich ist (dh das Programm wurde nicht geändert), drucken wir mit "world"und führen einen ungültigen Befehl aus a. Dies zwingt catchzum Wirksamwerden, was es uns ermöglicht, uns erneut zu überprüfen. Wenn unser Code diesmal nicht 97 ist, geben wir einen ungültigen Befehl aus, sodass unser Programm einen Fehler aufweist und den Fehlertext in die Ausgabe druckt. Wir haben dann clear()den Fehler und exitnormalerweise.

Es ist offensichtlich, dass bei ifManipulation einer der beiden Anweisungen die andere fehlerhaft ist. Wenn ein Teil von "world";manipuliert ifwird, verursacht der erste einen Fehler. Da es zusammenhängend sein muss, können wir nicht beide ifAnweisungen entfernen . Strings in der Mitte führen zu nicht übereinstimmenden Klammern oder dazu, dass die zweite {a}ausgeführt wird. Das try/ catchsoll den Fehler aus der ersten ifAnweisung abfangen, damit wir ihn richtig löschen können. Das Äußere "$( )"verhindert, dass die Saiten an beiden Enden abgeschnitten werden. Das Letzte ;aist zu verhindern, dass Teile der Mitte abgeschnitten werden, was zu gültigen Programmen führen würde (z. B. "it}a)";adie gedruckt werden it}a)und dann einen Fehler verursachen).

Es gibt verschiedene besondere Umstände:

  • Wenn das gc, gc<space>oder gc .\entfernt werden, Fehler wird das Programm schließlich mit etwas Geschmack eines aus Speicherfehler aus (aufgrund wiederholter Selbst Ausführung Anrufe) und wahrscheinlich Absturz die Schale (und vielleicht der Computer). Nicht getestet.
  • Wenn das <space>.\c.ps1oder .\c.ps1entfernt wird, stoppt das Programm und fordert zur Eingabe durch den Benutzer auf. Egal was der Benutzer eingibt, das Programm wird immer noch fehlerhaft sein, da die Anzahl der Größen falsch sein wird.
  • Wenn ein Teilstring, der an dem beginnt $und vor dem letzten endet, "abgeschnitten wird, gibt das Programm alles aus, was übrig bleibt, und anschließend einen Fehler, da er aungültig ist.

Mit folgendem verifiziert:

$x='"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yy='"$(try{if(($a=( .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyy='"$(try{if(($a=(.\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyyy='"$(try{if(($a=(c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'

for($i=1;$i-lt$x.Length;$i++){
  for($j=0;$j-lt($x.Length-$i);$j++){
    $y=($x[0..$j]+$x[($i+$j+1)..$x.Length])-join''
    $y>.\c.ps1
    $error.clear()
    if(!($y-in($yy,$yyy,$yyyy))){try{.\c.ps1}catch{};if(!($error)){exit}}
    $q++;
    write-host -n "."
    if(!($q%150)){""}
  }
}
"No success."

(Danke an Martin für seine umfangreiche Unterstützung!)

AdmBorkBork
quelle
3

C (gcc) (Linux -Werror=undef), 66 Bytes

main(a){a
=
1
/
(puts("world")/
6);
#if(7^__LINE__)
#else
}
#endif

Probieren Sie es online!

Große Herausforderung! Das war täuschend schwer, aber ich bin mir ziemlich sicher, dass ich jetzt ein gültiges Programm habe!

Verwendet einen Präprozessor-Befehl, damit keine Zeilenumbrüche entfernt werden können, da die schließende Klammer mainnur enthalten ist, wenn __LINE__==6. Es hält Sie auch davon ab, einfach nur mainganz auszuräumen, da dies #endifschwebend bleibt (es ist also wichtig, dass #endifes sich außerhalb von befindet main).

Ich habe verwendet, #elseweil ich ziemlich überzeugt bin, dass es keine Version gibt, bei der kein __LINE__==6Teilstring entfernt werden kann und die trotzdem wahr ist, da beide 6und __LINE__für sich genommen wahr sind. Es wird auch verwendet, damit -Werror=undefso etwas #ifdef(LINE__)nicht als falsch bewertet wird, sondern ein Fehler ist.

Mit gcc (zumindest unter Linux) wird putsdie Anzahl der gedruckten Zeichen (einschließlich der nachgestellten Zeilenumbrüche) zurückgegeben. Wenn Sie also einen beliebigen Teil der Zeichenfolge entfernen, wird der Wert puts("...")/6zurückgegeben 0, sodass 1/0eine Gleitkomma-Ausnahme ausgelöst wird . Beachten Sie, dass diese Ausnahme nur verursacht wird, wenn 1/0sie einem bestimmten Element zugewiesen a=ist. Daher ist die erforderlich.

Kein anderer Teil einer Zeile kann entfernt werden, ohne einen Fehler zu verursachen, normalerweise ein Syntaxfehler oder ein Verknüpfungsfehler.

Als Bonus gibt dies eine 86 - Byte - Lösung für C ++ ziemlich trivial, fügen Sie einfach #include <cstdio>und erklären , awie ein int. Probieren Sie es online! (C ++)

Chris
quelle
Wenn ich mich nicht irre, können Sie das entfernen, 1/während Sie die neue Zeile verlassen, und sie wird weiterhin ausgeführt .
Gastropner
@ Gastropner Richtig, Sie sind. 1Ich glaube, in der vorherigen Zeile wurde angenommen.
Chris
Leider gilt das Gleiche. Sie können dann entfernen =1. Ich denke, Sie müssen die 1 in eine eigene Zeile setzen.
Gastropner
@gastropner Ich denke du hast recht. Ich werde später mehr schauen. Vielen Dank!
Chris
2

PHP, 73 Bytes

<?=call_user_func(($p='ns')|(($f="u{$p}erialize"))?$f:'','s:5:"world"');

Explination

Ich gehe von der Standardkonfiguration von php.ini aus. Short_tags ist also deaktiviert. Dies bedeutet, dass Sie das nicht =aus dem Eröffnungs-Tag entfernen können .

Das ist im Grunde genommen <?=unserialize('s:5:"world"');.

Wenn Sie einen Teil der serialisierten Zeichenfolge entfernen, wird eine Fehlermeldung angezeigt.

Sie können es einfach entfernen unserializeund das Skript gibt nur den serialisierten String aus. Um dies zu überwinden, benutze ich call_user_func. Das Entfernen eines der Parameter führt zu einem Fehler.

'<?=call_user_func('unserialize','s:5:"world"');

Sie können jedoch entfernen un, um die serializeFunktion aufzurufen . Also nehmen wir 'ns' raus. Das Entfernen von Zeichen würde nicht zu einem falschen Funktionsnamen führen.

<?=call_user_func(($p='ns')&&($f="u{$p}erialize")?$f:'','s:5:"world"');

Wir werden eine Inline verwenden, um die variable Zuweisung mit dem Ausgabe-Tag zu verwenden. Anstatt zu verwenden, verwenden &&wir '|' zu verhindern, dass eine einzelne &oder die $fZuordnung entfernt wird

Sie könnten entfernen ='ns')&&($f="u{$p}erialize"und am Ende mit ($p)?$f:''. Deshalb füge ich zusätzliche Klammern hinzu $f="u{$p}erialize".

Hinweis

Technisch gesehen können Sie die öffnenden Tags entfernen, ohne einen Fehler zu verursachen. Dies ist dann aber kein PHP-Skript mehr, sondern nur noch eine reine Textdatei.

Jasny - Arnold Daniels
quelle
2
In Bezug auf Ihre letzte Notiz wäre die Klartextdatei immer noch ein gültiges PHP-Programm, oder? Ich bin mir also nicht sicher, ob dies gültig ist.
Calvins Hobbys
Es ist kein PHP mehr, sondern nur noch Klartext / HTML, also kein gültiges PHP-Programm mehr
Martijn
1

Matlab (77)

bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),'world',1:5)

Versuch es

Hinweis:

Im Anschluss an @ Optimiser Rat von einer CPR oder etwas entwerfen, war ich auf unvorhergesehene Teilzeichenfolge konfrontiert , die Führung zu jedem Kompilierungsfehler den Ball hielt , wenn sie entfernt, Beispiel: Entfernen arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),von diesem vorherigen bearbeiten feval(@(a)arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),'world')tut jeder Fehler generieren! In der letzten Ausgabe gab es auch einige, bsxfun(@(a,b)arrayfun(@(x)(x),prod(b,ismember(4,b))),'world',1:5)und bsxfun(@(a,b)a,'world',1:5)wenn Sie gefragt haben, wie es mir ging, als ich sie in meiner Ausgabekonsole herausfand, weinte ich wie ein Baby. Hier ist das Programm:

b=0;string='bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),''world'',1:5)'
for u=1:numel(string),for j=u:numel(string)-2,try a=eval([string(1:u) string(j+2:end)]);catch(b); a=0;end; if a~=0, ['here is it : ' string(1:u) string(j+2:end)],end;end;end

Ein Beispiel für ein nicht ursprüngliches Programm

bearbeiten:

Vielen Dank an alle neben @Martin für den Hinweis auf meinen vorherigen Code (keine Fehler).

Abr001am
quelle
1

SmileBASIC, 63 Bytes

REPEAT
A=1/(PRGSIZE(0,1)==63)?"world
UNTIL 1/(PRGSIZE(0,1)==63)
12Me21
quelle
1

Ein Birnbaum , 17 Bytes

Dieses Programm enthält Bytes mit gesetztem High-Bit (die nicht für UTF-8 gültig sind und daher nicht auf TIO gepostet werden können). Hier ist also ein xxdumkehrbarer Hexdump:

00000000: 7072 696e 7427 776f 726c 6427 23cd 4290  print'world'#.B.
00000010: bf                                       .

Erläuterung

Dies ist nur print'world'mit einer angehängten Prüfsumme. Ich habe mit brutaler Gewalt überprüft, dass keine der möglichen Löschungen ein Programm mit einer gültigen Prüfsumme enthält, sodass Sie nach einer möglichen Löschung einen Fehler erhalten.

Ziemlich langweilig, bindet aber den aktuellen Anführer, daher fand ich es lohnenswert, etwas zu posten.

ais523
quelle