Programming a Pristine World

90

9

Let's define a pristine program as a program that does not have any errors itself but will error if you modify it by removing any contiguous substring of N characters, where 1 <= N < program length.

For example, the three character Python 2 program

`8`

is a pristine program (thanks, Sp) because all the programs resulting from removing substrings of length 1 cause errors (syntax errors in fact, but any type of error will do):

8`
``
`8

and also all the programs resulting from removing substrings of length 2 cause errors:

`
`

If, for example, `8 had been a non-erroring program then `8` would not be pristine because all the results of substring removal must error.

Your task in this challenge is to write the shortest pristine program possible that takes no input but outputs any one of the following five words:

world
earth
globe
planet
sphere

Which word you choose is entirely up to you. The sole word plus an optional trailing newline should be printed to stdout (or your language's closest alternative). The shortest program in bytes wins.

Notes:

  • A standalone program is required, not a function.
  • The words are case sensitive; outputting World or EARTH is not allowed.
  • Compiler warnings do not count as errors.
  • The erroring subprograms can take input or give output or do anything else as long as they always eventually error.

Here's a stack snippet that will list what programs need to error given a potentially pristine program:

<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>

Calvin's Hobbies

Posted 2015-11-09T15:59:03.650

Reputation: 84 000

Does an exception being thrown in Java count as an error? What if I catch the exception? – geokavel – 2015-11-09T21:36:20.227

1@geokavel Yes. Catching the exception means it's no longer an error. – Calvin's Hobbies – 2015-11-09T21:37:40.157

34Twice as many deleted answers as non-deleted. That's an achievement! – DLosc – 2015-11-09T22:42:49.247

1Can a program read its own source code? – Shelvacu – 2015-11-11T17:57:56.173

@Shel Sure. (4more..) – Calvin's Hobbies – 2015-11-11T18:02:25.637

2Where to view the gravegard of "close but no cigar" answers and their comments? – Vi. – 2015-11-12T14:28:49.843

1

@Vi. Get 2,000 rep so you can view deleted posts.

– ThisSuitIsBlackNot – 2015-11-12T16:30:16.227

What kind of errors are you talking about? just Compile and Runtime errors that make the program crash, or also logical errors that don't make the program crash but return a wrong output? – Nzall – 2015-11-12T23:52:21.127

@NateKerkhofs Errors that crash the program or prevent it from running. – Calvin's Hobbies – 2015-11-12T23:54:06.983

@Shel not sure if I am missing the context of your question because Calvin's PCG question makes my brain hurt but <php echo file_get_contents(__FILE__); ?> – MonkeyZeus – 2015-11-13T18:27:27.413

@MonkeyZeus Sorry, I was asking if it was allowed, not if it was possible. – Shelvacu – 2015-11-13T19:07:54.090

Makes me wonder if Mathematica can have a pristine program that does anything useful. – LLlAMnYP – 2015-11-14T23:24:41.900

1This answer is now the shortest — should it be accepted instead? – Aidan F. Pierce – 2018-04-15T18:45:58.323

Is there a PristineScript language that has a built-in checksum in every program? – dan04 – 2019-04-09T23:47:33.887

Answers

48

Rail, 24 bytes

$'main'    #
 -[world]o/

I think this works. And it's both short and readable (as far as Rail goes).

  • If the removed substring includes any part of $'main' we get Internal Error: Crash: No 'main' function found.
  • If the removed substring includes the #, there is no way for the program to exit cleanly, so it will always terminate with Crash: No valid move. I believe that it's not possible to delete a substring such that the track forms a valid (infinite) loop.
  • If the removed substring is in front of the #, it will be disconnected from the end of the track, so the train will crash (with the same error as above).
  • If the removed substring is after the #, it will also disconnect the # from the end of the track (and potentially even the beginning of the track from the entry point $). So again the same error.

As for the actual program: every Rail program needs to have a $'main' (or a longer variant, but we're golfing here) as an entry point into the function and the train starts on the $ going South-East. Everything on that first line can be part of the track though, so removing the 'main' the track is:

$          #
 -[world]o/

The - and / are simply pieces of rail which we need to let the train take those 45° turns.

[world] pushes the string world and o prints it. # marks the end of the track - the only way to safely terminate a Rail program.

Interestingly, this solution is only possible because Rail allows the tracks to go through the main line - if that wasn't possible # would be after the first newline and the code could always be shortened to

$'main'
 #

which is a valid program that doesn't do anything. (Non-space characters between ' and # wouldn't affect that.)

Also quite interesting: if I had just golfed the task printing world it wouldn't have been much shorter or simpler:

$'main'
 -[world]o#

Martin Ender

Posted 2015-11-09T15:59:03.650

Reputation: 184 808

4What if I remove any char between [ and ]? – Martin Lütke – 2015-11-09T21:48:47.523

@MartinLütke it will disconnect the / from the #. – Martin Ender – 2015-11-09T21:49:42.197

2@MartinLütke You could not only remove the brackets since they are not contiguous. – Calvin's Hobbies – 2015-11-09T22:06:10.833

What if remove the newline between the two lines? – Vi. – 2015-11-12T14:32:52.377

1@Vi. That disconnects the $ from the start of the track, so the train crashes immediately (Rail expects the track to continue South-East of the $). – Martin Ender – 2015-11-12T14:33:25.803

45

Funciton (186 136 bytes in UTF-16)

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

This program prints “world”.

Most substrings you remove from this will stop it from being a complete box, which the parser will complain about. The only possible removals that leave a complete box are:

 ╔══════════════╗
|║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)
|╚══════════════╝

Most of these remove the dangling end at the top right of the box, which is the output connector. Without this loose end, the box is just a comment:

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

This is no longer a valid program because the parser expects a program with exactly one output:

Error: Source files do not contain a program (program must have an output).

The only possibility that leaves an output connector is the last one of the above, which leaves this:

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

However, this number does not encode a valid Unicode string in Funciton’s esoteric UTF-21. Try to run this, you get:

Unhandled Exception: System.ArgumentOutOfRangeException: A valid UTF32 value is between 0x000000 and 0x10ffff, inclusive, and should not include surrogate codepoint values (0x00d800 ~ 0x00dfff).

Therefore, this program is pristine.

Timwi

Posted 2015-11-09T15:59:03.650

Reputation: 12 158

3I feel like you got lucky on the last case (not that it's that easy to accidentally get a valid Unicode sequence, but still...) – Esolanging Fruit – 2017-07-13T02:30:25.817

35

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

Properties:

  1. You can't remove any part of int main() without a compile error.
  2. You can't remove the modify the macros expansion AT ALL, removing a at all means main() never gets {, removing b at all means our line doesn't end in a ;, removing < means std::cout<'w' causes an error, and removing << causes std::cout'w', 'w''o', etc.
  3. You can't remove parameters from the macro definition or invocation, the only valid names for the definition would be I(a),I(b) which never match and I which expands to before (; on the other hand using I(, causes <<<<, and ,) drops the semi-colon (barring any other errors).
  4. You can't remove part of all of std::cout without running into a leading <<, and therefore cannot remove any of #include<iostream> in the beginning without a compile error.
  5. You can't remove any part of a single character, '' has an empty character error and 'w,, etc... try to making everything into one character.
  6. You can't remove the left/right side of a macro without leaving too many ) or ( on the other side, e.g. you cannot do things like I('w',I('r'.

Compiles online using Visual C++.

Once again this not an exhaustive proof. If you think you can get it too work without section be sure to let me know.

Previous versions used a considerably different approach and was proved to not be pristine so I've removed those scores.


Verification:

The following program has confirmed this version is pristine using the cl compiler from Visual C++ 2010. Wished I had bothered to write this sooner:

#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

Posted 2015-11-09T15:59:03.650

Reputation: 1 948

1We note that while this is pristine on this compiler, not so on all compilers. – Joshua – 2015-11-11T02:42:48.013

1Please give an example.... – Linus – 2015-11-11T05:10:12.633

3On some compilers the empty C++ program yields a program that does nothing. Depending on the implementation of the iostream, #include <iostream> might also compile. – Joshua – 2015-11-11T16:13:27.453

5@Joshua Only subprograms of length 1 or higher matter, so it's irrelevant what the empty program does. – ThisSuitIsBlackNot – 2015-11-12T20:39:36.737

Using the online compiler you link, #include<iostream> #define I(a,b)a<<b compiles just fine by itself. – Comintern – 2015-11-14T04:57:04.547

2@Comintern, not really. If you don't check the box to run the executable the /c option is automatically included and it compiles (as if creating a library and not a program). If you check the run box the site does not include /c, you will not get a success message, and instead find the natural "LINK : fatal error LNK1561: entry point must be defined". – Linus – 2015-11-15T00:10:59.080

33

Python 3, 79 33

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

open(1,'w') opens standard output, then we print the string. write returns the number of characters written. This is used to harden against substring removal: Removing part of the string causes something other than 5 to be returned, and 5 minus that value then evaluates to true. But that causes the if-body to be executed and a is undefined.

This is based on Anders Kaseorg's clever pristine quine here.

As only a single statement needs to be verified this is much shorter than the old solution, but also less general.

Old solution:

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

To verify that it really is a pristine program:

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

Some key points:

  • Every executed statement could be deleted. Verifying that q has been executed requires a statement outside of q. The try solves that nicely, by requiring at least two statements, neither of which can be deleted fully.
  • Verifying that q has executed happens by evaluating r at the end.
  • Verifying that q was not modified is achieved by eval(q[17:]), which has to evaluate to None for q to be executed.
  • The if condition is a bit tricky to get right. To ensure that it was evaluated it has the nice side effect of setting e, which is needed to set r. (This is the reason I used Python 3, expr as a function does wonders for expression-level side effects.)

Philipp

Posted 2015-11-09T15:59:03.650

Reputation: 491

Isnt the challenge that no removal would result in a syntax error? You seem to provoke runtime errors. – Martin Lütke – 2015-11-09T22:03:18.107

5@MartinLütke Any type of errors are fine. – Calvin's Hobbies – 2015-11-09T22:03:42.963

1Um, isn't this 79 bytes? – The Matt – 2018-07-06T02:39:51.233

@TheMatt Yeah? I just counted them again and you seem to be right. Maybe past-me counted CRLF newlines... How embarrassing. Thanks! – Philipp – 2018-07-06T22:46:03.963

26

Haskell, 61

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

Any type of error is OK? In that case:

Haskell, 39

main=putStr$take 5$(++)"world"undefined

Martin Lütke

Posted 2015-11-09T15:59:03.650

Reputation: 391

Does this work if you remove one of the letters? – lirtosiast – 2015-11-09T23:18:04.153

It will crash during execution. Because it will try to evaluate undefined. – Martin Lütke – 2015-11-09T23:20:13.973

This is excellent. Lazy evaluation FTW, it appears! – DLosc – 2015-11-10T00:22:48.987

1I wish 'inits' was in the prelude :(. Then: main=putStr$inits"world"!!5 (27 bytes) – Martin Lütke – 2015-11-10T18:14:22.513

17

JavaScript, 74 73 35 bytes

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

It turns out the answer was much simpler than I thought...

Explanation

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

Posted 2015-11-09T15:59:03.650

Reputation: 10 181

remove everything except a="world", does not error – anOKsquirrel – 2015-11-11T00:04:36.030

3@anOKsquirrel Only a single substring can be removed. – Dennis – 2015-11-11T02:24:09.000

4I went through this like "Could I remove this? No, this error would occur. Can this be deleted? Well, I guess it would cause this other error. Aha! Those chars can be removed! Oh wait..." +1 – ETHproductions – 2015-11-11T03:26:03.103

if(a="world")["bol"+a[4]] does not error. – anOKsquirrel – 2015-11-11T13:13:25.200

@anOKsquirrel There are two opening brackets after the if. if((a="world")["bol"+a[4]] does cause an error. – user81655 – 2015-11-11T14:55:24.073

You can remove the content of the alert and it does not thows an error. – Naouak – 2015-11-11T17:29:46.510

@Naouak Do you mean the b=a? Because if you do that it will throw an error because b is not defined at b[2]. You probably thought that because you tested it multiple times in the same environment which caused b to already be defined. – user81655 – 2015-11-11T18:05:18.877

@user81655 dang it you're just too smart ;-; – anOKsquirrel – 2015-11-11T18:12:45.643

remove the ! and you still get output. It also errors, but it outputs which is against the rules. Actually, no, it's allowed dangit – anOKsquirrel – 2015-11-11T18:14:55.167

5Holy cow, it's twice as impressive now! Wish I could +1 again... – ETHproductions – 2015-11-11T21:03:51.713

16

Funciton, 143 142 136 bytes

Score is in UTF-8 as usual, as UTF-16 would be two bytes larger (due to the BOM).

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

So, I've been contemplating a Funciton answer for a while and I figured it would be impossible, because you could always remove a full line and the code would still form a valid block. Then I talked to Timwi about it, and he figured out that you can just put the entire number in a single line, such that removing it would break the program for lack of an output connector.

But literals on a single line are notoriously expensive, both because of the larger character count and because of the larger number of non-ASCII characters. And his mention of an "empty comment" block got me thinking...

So I came up with this more efficient solution which uses an additional empty comment block which breaks when you try removing anything which would leave the literal block in tact:

  • We can't possibly remove the third line, because then we'd remove the output connector.
  • If we remove the second line, the comment block loses its top edge and breaks.

That leaves two options (thanks to Steve for pointing that out):

  • Remove the fourth line. That leaves both boxes in tact. However, when the resulting integer 19342823075080880373 is decoded, the corresponding string would contain the code point 0x18D53B which is not a valid Unicode character, System.Char.ConvertFromUtf32 crashes with an ArgumentOutOfRangeException.
  • Remove a full line starting after the top-right corner. Again, both boxes are left in tact, but the resulting integer 508088037380718711 would contain two invalid code points 0x1B0635 and 0x140077, leading to the same exception.

Note that even without the empty comment block, removing the second line would lead to an invalid code point. But the comment block prevents that we're taking a line from inside the second line, to get an integer like 193428037380718711 for instance, which would not cause an error.

Martin Ender

Posted 2015-11-09T15:59:03.650

Reputation: 184 808

What happens if you remove the substring starting with the character after the output connector and finishing exactly 1 line later? i.e. removing the middle line of the comment block and the line containing "80718711" in the main block, but leaving corners of both boxes intact. – Steve – 2015-11-11T12:59:22.167

@Steve I've amended the answer to cover that case. After looking into it a bit more, this actually allowed me to save two characters/six bytes. – Martin Ender – 2015-11-11T15:24:31.547

15

Java 8, 301 bytes

Because every question needs a Java answer.

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

Expanded

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

Explanation

  • public static main(String[]a){} is required.
  • If the field declarations are removed (or made non-static), the first static block can't find them.
  • If the static block is removed (or made non-static), the fields aren't initialized.

The hardest part:

  • If the final keyword is removed, the second line evaluates to 1/(8-8), causing a / by zero exception.

Ypnypn

Posted 2015-11-09T15:59:03.650

Reputation: 10 485

Why can't you remove the insides of any of the print statements? – Fund Monica's Lawsuit – 2016-04-11T20:33:40.103

2@QPaysTaxes There isn't an empty System.out.print() method. There is for println(), but not for print(). So if you would remove d='d' it would give The method print(boolean) in the type PrintStream is not applicable for the arguments () as error (And if you would remove d= it would give The blank final field d may not have been initialized as error). – Kevin Cruijssen – 2016-10-12T14:24:38.730

11

Ruby, 36

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

We assign s="planet", then write that string to STDOUT. This returns the number of characters written. We xor that with 6, so that if anything other than 6 characters were written, we'll get a nonzero integer. Then we slice into s with that index. Only the 0th character of s, "p", is a valid code string (a no-op). We pass that to eval, using the (*[argument]) syntax which is equivalent to just (argument) except that it's not valid outside of a method call.

Pristineness verified programmatically on Ruby 1.9.3 and 2.2

histocrat

Posted 2015-11-09T15:59:03.650

Reputation: 20 600

Holy crap. This is amazing. – clap – 2015-11-23T16:37:57.727

What happens if you remove the *? – LegionMammal978 – 2015-12-10T12:16:03.640

Then you're passing an array to eval instead of a string, which is an ArgumentError. – histocrat – 2015-12-10T13:40:26.283

10

><>, 17 bytes

e"ooooo7-c0pBhtra

Try it online!

Prints "earth".

The only way a ><> program exits without an error is executing the ; character, which is a problem as you can just remove all the characters before that, so that ; is the first character executed. You can get around that by using the p command to modify the program to include ; during execution instead. Removing any section of the code causes the ; to never be produced causing errors via the invalid instructions B, h and t, stack underflow, and infinite loops making it eventually run out of memory. I only had to make sure that all the infinite loops kept filling up the stack.

All variants were tested using this python snippet:

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

added to (a slightly modified version of) the official fish.py interpreter by the creator of ><>. Out of 152 possible sub-programs, 92 errored from invalid instructions, 18 from stack underflow, and 42 from running out of memory.

Funny facts, the first version of this e"ooooo6-c0pAhtra had a couple of freak sub-programs that managed to use the put command to place a [ which would clear the stack, in place of the invalid instruction A. Also, "earth" is the only one of the phrases that will work with this method, because the first letter, e is a valid instruction in ><>. Otherwise the " command has to be placed at the front of the program, and a valid subprogram could be just " by itself.

Jo King

Posted 2015-11-09T15:59:03.650

Reputation: 38 234

10

C#, 128 118 101 bytes

Thought of abusing the contiguous substring rule.

The Code

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

Why It Works

  1. class h and static void Main() are required.
  2. Removing any of the chars in 'w','o','r','l','d' causes an error because the char array is initialized with length 1*5.
  3. You can't remove the contents inside Main() without violating the contiguous character rule as parts are separated by preprocs. (See below)

Before Golfing and Separation

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

Verified With

https://ideone.com/wEdB54

EDIT:

  • Saved some bytes by using #if !x instead of #if x #else.
  • Used => func syntax. #if!x instead of #if !x. Credits to @JohnBot.
  • Due to => func syntax, extra preproc condition can be removed.

Helix Quar

Posted 2015-11-09T15:59:03.650

Reputation: 211

Hi helix! Do you think you could explain how and why your answer works a bit more? – isaacg – 2015-11-10T07:12:14.843

@isaacg Edited. Proof to follow. – Helix Quar – 2015-11-10T07:33:41.533

I can't get it to run without static on Main. – Johnbot – 2015-11-10T12:54:41.653

@Johnbot Yeah. Must've miscopied. Fixed. – Helix Quar – 2015-11-10T13:09:23.167

You can save a character by making Main an Expression-bodied function member and 2 more by removing the spaces before the preprocessor condition: 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. That's 115 by my count.

– Johnbot – 2015-11-10T13:20:39.873

10

MATLAB, 37 36 33 bytes

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

Since I am not sure if we are allowed to also output ans=, I had to find some work-around to output in a proper way. Using fprintf by itself did not work, because no matter what I tried it simply refused to error. Using disp by itself was not an option, as it would only take 1 argument and that argument itself obviously would also execute without errors.

If it's no problem to also include ans= in the output, then MATLAB can be done with 20 bytes:

reshape('world',1,5)

slvrbld

Posted 2015-11-09T15:59:03.650

Reputation: 619

i really must learn more about built-in functions (+1) // btw your program is scored 20 – Abr001am – 2015-11-11T13:51:18.827

2That really depends on how strict the rules are. They state that only 'world' (+ optional trailing newline) should be printed, so then it's 33 bytes. – slvrbld – 2015-11-11T15:38:48.660

Yeah, we'll count this as 33. Thanks for understanding :) – Calvin's Hobbies – 2015-11-11T15:40:12.213

8

Ruby, 34

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

This has a few components:

eval(*[ expr ]) is borrowed from histocrat's answer, and is pristine as well as verifying the return value of expr is a valid ruby program that doesn't error. method(*arr) is a ruby syntax that calls method with the values of arr as the arguments. The reason this is needed here is because it is only valid as parameters for a method, so that if eval is removed, (*[expr]) is a syntax error. If expr is removed, eval complains about not having enough arguments

$>.write("world")-1 cannot be mangled except for inside the string and the subtraction. $>.write("world") writes "world" to STDOUT and returns the number of characters written, then subtracts 1. Therefor if the program is un-mangled the value will be exactly 4. If it is mangled (either the -1 is removed or the string shortened) then it will return one of -1,0,1,2,3, or 5. Any other mangling results in a syntax error.

Calling chr on a number returns the character represented by that number. So, when called on the result of the above example, it errors on -1, and returns a single-character string otherwise.

I'm not actually sure why this is, but it seems that ruby interprets \x04 as a whitespace character, which means the expression is valid (empty ruby programs do nothing). However, any of the other characters (\x00 - \x03 and \x05) result in Invalid char '\x01' in expression. I found this by simply iterating over possible math I could do to the number returned. Previously I had used

$>.write("planet
")*16

where "planet" plus a newline was 7 chars, times 16 to get 112 for p, the only single-letter function in ruby defined by default. When given no arguments, it is effectively a no-op


Honorable mention: $><<"%c"*5%%w(w o r l d) is very close but not pristine. Removing "%c"*5% results in no errors. Mini-explanation:

$> is stdout, and << is a function being called on it. "%c"*5 generates the format string "%c%c%c%c%c", which then then trys to be formatted (%) by an array: %w(w o r l d) which is a shorter version of ['w','o','r','l','d']. If there are too few or too many elements in the array such that it does not match the format string, an error is thown. The achilles heel is that "%c"*5, and %w(w o r l d) can both exist independantly, and $><< only needs an argument of either. So there are a few different ways of mangling this program into non-erroring cousins.


Validated using this:

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

Posted 2015-11-09T15:59:03.650

Reputation: 610

An explanation along the lines of histocrat's answer would be nice. It seems like you're using the same basic approach, but since I don't know Ruby, I can't understand the details.

– ThisSuitIsBlackNot – 2015-11-11T19:50:04.213

@ThisSuitIsBlackNot Did my best, anything you don't understand? – Shelvacu – 2015-11-11T20:39:13.727

Excellent explanation, thanks! – ThisSuitIsBlackNot – 2015-11-11T20:53:53.280

6

Python 3, 43 bytes

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

Try it online!

How it works

To protect against substring deletions, we use open(1,"w").write instead of print. In Python 3, write returns the number of written characters, which we will verify is 5 to ensure that no part of the string was deleted. We do this by looking up the return value in the dictionary {5:[]}, and looping over the result with for[]in…:a, which will fail if we didn’t get an empty iterable or if the for statement is deleted.

Anders Kaseorg

Posted 2015-11-09T15:59:03.650

Reputation: 29 242

5

Perl 5.10+, 71 63 bytes

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

Prints world with a trailing newline. Run like this:

perl -M5.010 file

This relies on the byte count of the source code, so file must contain the above code and nothing else (no shebang, no trailing newline). Perl 5.10+ is required for say and the defined-or operator //.


It's incredibly difficult to make a pristine program with Perl, because:

  • Any bareword identifier (e.g. foo, a, _) is a valid statement with no strict 'subs'; (the default). This means the program can neither begin nor end with a letter, number, or underscore.

  • As tchrist explains, "Identifiers specified via symbolic dereferencing have absolutely no restriction whatsoever on their names." This means the program cannot begin with any of the sigils $, @, %, or *, since removing all but the first and last character would always leave a valid variable name.

  • Many built-in functions (including most functions capable of producing output) work on $_ by default, so calls will often work even if you remove the argument (e.g. say"world" vs. say).

How it works

This solution was inspired by Naouak's Node.js answer, which checks its own length to make sure characters haven't been removed.

The program has two sections, one inside parentheses and the other inside a block:

(...);{...}

The first section reads the source file and dies if it is less than 63 characters long. The second section checks that the read executed successfully. If either section is removed (with or without the enclosing parentheses or curly braces), the other section will throw an exception.

Removing the middle or the left or right side of the program will unbalance the parentheses and/or curly braces, causing a syntax error.

If the first die is altered (to d, e, di, de, or ie, which are all valid identifiers), the length check becomes:

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

which evaluates to:

@{\'di'};

This takes a reference to a string and tries to dereference it as an array, producing an error:

Not an ARRAY reference

If any other statement is altered, the length check will fail and the program will die.


Verified pristine with the following program:

#!/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

Posted 2015-11-09T15:59:03.650

Reputation: 1 050

4

Javascript(Node.js), 93 95 bytes

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

Check it's own size twice so if any chars is missing an error is thrown. The length is 156 because Node.js prepends function (exports, require, module, __filename, __dirname) { to the code on runtime.

Thanks Martin Büttner for pointing out an error. Fixed now.

Naouak

Posted 2015-11-09T15:59:03.650

Reputation: 349

4

Ruby + coreutils, 33 27 26 bytes

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

Try it online!

Backticks in ruby execute the command inside them and return whatever the program put into STDOUT as a string. The #{expr} syntax allows embedding of expressions in strings and backticks. This program could be rewritten (non-pristinely) as:

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

IO#write returns the number of bytes written, so if the string is shortened then it won't be the right number. #{} embedding automatically makes the number into a string. If some piece is removed, and it doesn't result in a syntax error, the wrong command will be run. If part of "world" is removed than one of base04 through base54 will try to run.

The newline, whether in or out of the string, is required. Otherwise the first 5 characters(`base) can be removed, making the whole line a comment. Also there must be one or more characters between the first backtick and #, otherwise the { can get removed to make the whole thing a shell comment.


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

exec Replaces the current ruby process with the command specified. See my other answer for an explanation of the meth(*[]) syntax and the neccesity of it.

(s="ec%co earth") assigns the string "ec%co earth" to the variable s. Assignments return what was assigned, so the string is also returned.

"format string %d" % 5 is syntactic sugar for sprintf("format string %d",5), however spaces around the % are not neccesary.

s[10] gets the character in the string at index 10. When un-mangled, this character is "h", the last letter in the string. However, removing any characters in the string means the string is shorter, so there is no character at index 10, so s[10] returns nil, and "%c" % nil causes an error.

if %s[10] is removed, then ruby tries to run the command ec%co earth which doesn't work.

Changing 10 to 1 or 0 also results in an unknown command (either eceo or ecco). Removing it entirely is technically not a syntax error since it calls the method #[] on the string, but then it complains about not enough arguments.


A note on solving this in general: You must have some wrapper that verifies the code inside in an abstract sense while being pristine itself. For example, a program with division at the end (blablabla/somevar) will never work because a division can always be removed(blablabla). These are some such wrappers I've used so far:

  • eval(*[ code ]) used by histocrat and in my first answer. Validates that the output is a valid ruby program
  • exec(*[ code ]) used above, validates that the response is a valid command
  • `#{ code }`

The backtick syntax also runs a command (and therefor validates that it's a valid one), however STDOUT is captured as a string instead of being output as the parent process' (Ruby's) STDOUT. Due to this I was not able to use it for this answer, EDIT: I made it work. Limitations outlined above.

Edit: Thanks to @histocrat for pointing out some flaws

Shelvacu

Posted 2015-11-09T15:59:03.650

Reputation: 610

Cool approach! You can (and therefore must) remove the space between write and the start of the string, but I don't think that affects pristineness. Also, on my machine base64 will hang waiting for input, which might be against the rules. – histocrat – 2017-07-13T13:11:53.623

@histocrat Wow, I'm suprised that $>.write"world" works, thanks! As for base64 waiting for input, it seems to vary by system. TIO works fine. That makes it even more fuzzy as to whether it follows the rules. – Shelvacu – 2017-07-13T21:39:08.317

3

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

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

Try it online!

Great challenge! This was deceptively hard, but I'm pretty sure I have a valid program now!

Uses a preprocessor command so that no newlines can be removed, since the closing bracket to main is included only if __LINE__==6. It also keeps you from just clearing out main entirely, since that leaves #endif floating (so it is important that #endif is outside of main).

I used #else because I've become fairly convinced there's no version of __LINE__==6 that can't have a substring removed and still be true, since both 6 and __LINE__ by themselves are truthy. It also uses -Werror=undef so that something like #ifdef(LINE__) doesn't evaluate to false, but is an error.

With gcc (on Linux, at least), puts returns the number of characters printed (including the trailing newline), so removing any part of the string makes puts("...")/6 return 0, so that 1/0 causes a floating point exception. Note that this exception isn't caused unless 1/0 is assigned to something, so the a= is required.

No other part of any line can be removed without creating an error, usually a syntax error or a linking error.

As a bonus, this gives an 86 byte solution for C++ pretty trivially, just add #include <cstdio> and declare a as an int. Try it online! (C++)

Chris

Posted 2015-11-09T15:59:03.650

Reputation: 1 313

Unless I am mistaken, you can remove 1/ while leaving the newline and it will still run.

– gastropner – 2018-07-06T09:07:22.963

@gastropner Right you are. 1 was supposed on the previous line I believe. – Chris – 2018-07-06T09:27:17.457

Sadly, the same thing holds. You can then remove =1. I think you need to put the 1 on a line on its own. – gastropner – 2018-07-06T09:32:49.100

@gastropner I think you're right. I'll look more later. Thanks! – Chris – 2018-07-06T09:40:30.617

3

PowerShell, (97 bytes + 5 for program name) = 102 Bytes

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

Checks itself before it wrecks itself ... twice.

Expects to be saved as c.ps1 and executed from the local directory as such:
PS C:\Tools\Scripts\Golfing\> .\c.ps1.

The alias gc is short for Get-Content and is similar-ish to a cat reading a file (in this case, our execution path .\c.ps1). We get the .Length of the file, set it to $a, and check whether it's not equal to 97 with -eq97. If it is equal (i.e., the program has not been modified), we print with "world", and execute invalid command a. This forces the catch to take effect, which allows us to check ourselves again. This time, if our code is not equal to 97, we throw an invalid command so our program has errored and printed error text to the output. We then clear() the error and exit normally.

It's obvious that if either if statement is tampered with, the other will have an error. If any portion of "world"; is tampered with, the first if will cause an error. Since it has to be contiguous, we can't remove both if statements. Strings in the middle will result in mismatched parentheses, or will result in the second {a} getting executed. The try/catch is to catch the error from the first if statement so we can properly clear it. The outer "$( )" prevent strings from either end getting snipped. The final ;a is to prevent portions of the middle getting snipped that would result in valid programs (e.g., "it}a)";a, which will print it}a) and then error).

There are several special circumstances:

  • If the gc, gc<space> or gc .\ are removed, the program will eventually error out with some flavor of an out of memory error (due to repeated self-execution calls) and likely crash the shell (and maybe the computer). Not tested.
  • If the <space>.\c.ps1 or .\c.ps1 are removed, the program will stop and prompt for user input. No matter what the user enters, the program will still error since the size counts will be wrong.
  • If a substring starting at the $ and ending before the last " is snipped, the program will output whatever remains and then error because a is not valid.

Verified with the following:

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

(Thanks to Martin for his extensive assistance!)

AdmBorkBork

Posted 2015-11-09T15:59:03.650

Reputation: 41 581

2

PHP, 73 bytes

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

Explination

I assume the default php.ini configuration. So short_tags is disabled. This means you can't remove the = from the opening tag.

This is basically <?=unserialize('s:5:"world"');.

If you remove any part of the serialized string you'll get an error.

You can simply remove unserialize and the script will just output the serialized string. To overcome this I use call_user_func. Removing one of the params will result in an error.

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

However you can remove un, to call the serialize function. So we take out 'ns`. Removing any characters would no result in an incorrect function name.

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

We'll use an inline if to using variable assignment with the output tag. Instead of using && we use '|' to prevent removing a single & or removing the $f assignment

You could remove ='ns')&&($f="u{$p}erialize" and end up with ($p)?$f:''. Therefor I add extra parenthesis around $f="u{$p}erialize".

Note

Technically you can remove the opening tags without producing an error. This is than however no longer a PHP script but just a plain text file.

Jasny - Arnold Daniels

Posted 2015-11-09T15:59:03.650

Reputation: 129

2About your last note, the plain text file would still be a valid PHP program, right? So I'm not sure this is valid. – Calvin's Hobbies – 2015-11-11T05:54:53.117

It's no longer PHP, but plaintext/html, thus not a valid-php-program anymore – Martijn – 2015-11-11T11:17:28.930

1

SmileBASIC, 63 bytes

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

12Me21

Posted 2015-11-09T15:59:03.650

Reputation: 6 110

1

A Pear Tree, 17 bytes

This program contains bytes with the high bit set (that aren't valid UTF-8 and thus can't be posted on TIO), so here's an xxd reversible hexdump:

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

Explanation

This is just print'world' with a checksum appended. I've verified by brute force that none of the possible deletions give a program with a valid checksum, so you get an error after any possible deletion.

Fairly boring, but ties the current leader, so I felt it was worth posting.

ais523

Posted 2015-11-09T15:59:03.650

Reputation: 11

1

Matlab(77)

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

try it

Note:

Following @Optimiser's advice of designing a CPR or something, I was faced to unforeseen substring which didnt lead to any compilation error when removed, example: removing arrayfun(@(x)a(x),prod(b,ismember(4,1:5))), from this previous edit feval(@(a)arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),'world') doesnt generate any bug! also, for recent same edition, there were bsxfun(@(a,b)arrayfun(@(x)(x),prod(b,ismember(4,b))),'world',1:5) and bsxfun(@(a,b)a,'world',1:5),if you asked about how was I when finding them out in my output console, I cried like a baby, so here is the program:

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

An example of a nonpristine program

edit:

Thanks to everyone beside @Martin for pointing my previous code's (not-errors) out .

Abr001am

Posted 2015-11-09T15:59:03.650

Reputation: 862