Exploit "free whitespace"

20

Suppose a codegolf challenge doesn't count whitespace in the length of your program. Cheat this system by encoding your script into whitespace, and golf a script which decodes and executes embedded whitespace.

Example

My solution to JBernardo's Meta Golf Challenge was to encode Sage (or Python) code into whitespace, and golf the decoder.

s = ' '
for c in '<lots of whitespace>'.split(s):
    s+=chr(len(c))
exec s

The encoding is to take a script, prepend a newline, and for each character c in the script, output ord(c) tabs followed by a space. Prepending a newline is necessary since I'm using Python and I start the script s with a space.

Scoring

A complete solution contains a description of the encoding you use (if it's complicated, provide a script), and a 'decode-and-execute' script. Your score is the number of non-whitespace characters in the decode-and-execute script.

Whitespace (the language) is forbidden

Moreover, any language which has a complete set of operators which only use whitespace characters is not allowed: I'll accept the lowest nonzero score.

boothby

Posted 2011-09-01T18:01:31.867

Reputation: 9 038

Answers

8

Golfscript, 12 chars

String delimited by ' goes before these 10 chars:

n/{,}%''+~

Each line is decoded into one character, whose ASCII (probably Unicode, in fact) value is the length of the line.

Unfortunately if I try pasting my Hello World example, Markdown removes the extra spaces, even in a <pre> block.

Peter Taylor

Posted 2011-09-01T18:01:31.867

Reputation: 41 901

2Since whitespace at the beginning of a program is always non-functional, .n/{,}%+~ would work as well. – Dennis – 2015-10-08T15:56:07.340

9

CPAN, 16

use Acme::Bleach;

CPAN has it all. Or at least, just the right module.

J B

Posted 2011-09-01T18:01:31.867

Reputation: 9 638

This was actually the first thing I thought of when I saw this challenge. I argue it isn't cheating because, it DOES have non-whitespace characters and, the entire spirit of the challenge is to encode everything but a decoder stub. This decoder stub just happens to have been built several decades ago ;-) – Cort Ammon – 2015-10-08T21:24:39.317

I call cheat on this, that is a complete set of operators that is nothing but whitespace – ratchet freak – 2011-09-01T19:34:47.417

5This is not a cheat. It's cheap, but acceptable. – boothby – 2011-09-01T21:59:17.790

1This program does nothing. None of the WS is there. BOOOOOO!!!! Please repost this with a program that does something useful here. Keep the Acme::Bleach use, but take advantage of it. – Thomas Eding – 2011-09-05T22:30:14.803

1@trinithis: as do none of the other programs presented here. Why pick specifically on this one? – J B – 2011-09-06T07:39:17.080

I noticed it and it stands out as a what does this do, it only looks like it imports. – Thomas Eding – 2011-09-06T15:37:19.330

Well, surprisingly enough, that's all that's needed. – J B – 2011-09-06T20:50:06.440

3

Perl, 29

$_="";s/     */chr length $&/ge;eval

Inside that s/// are a tab then a space. The encoding is an ultra-basic encode with spaces, precede with tabs.

Try this one on the command line:

$ tr ST ' \t' <<< '$_="TSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"; s/TS*/chr length $&/ge; eval' | perl

Edit: well, lol, I can't find a proper way to copy-paste the tab/space mix. Believe me, it works at home :) Update: there, there, encoded with tr

J B

Posted 2011-09-01T18:01:31.867

Reputation: 9 638

you can put tabs in with \t and we'll believe it works with whitespace... – boothby – 2011-09-05T07:14:10.840

@boothby: oh, better than that, I can have the \t interpreted by the shell and actually have the damn thing work demonstrably. Doing that in a few hours. – J B – 2011-09-05T09:04:06.080

3

JavaScript

Replace \t with a tab to get the posted character count.

Standard (64 characters)

eval(eval("'<code here>'".replace(/\t */g,function(s){return"\\"+s.length})))

Arrow function (49 characters)

eval(eval("'<code here>'".replace(/\t */g,(s)=>"\\"+s.length)))

Encoder program for both

for(var i = 0, si = prompt("Enter the code."), so = ""; i < si.length; ++i) so += '\t' + Array(+si.charCodeAt(i).toString(8)).join(' '); prompt("Here is the result.", so);

PleaseStand

Posted 2011-09-01T18:01:31.867

Reputation: 5 369

Replace (s)=>... in the arrow function to s=>... to save two bytes – andrewarchi – 2017-06-15T05:06:26.713

Keep spaces between any two char and at worst use jsfuck to make it work(and better use " t " [ 1 ] to mean "t") – l4m2 – 2018-12-11T11:40:09.783

44B eval("".replace(/ +/g,s=>' []+!()'[s.length])) – l4m2 – 2018-12-11T11:42:33.043

2

C (99 characters)

main(c, p)
{
    char *s = "<code here>";
    for (p = popen("cc -xc -oa -", "w"); *s;)
        *s++ - 9 ? c -= putc(c, p) : ++c;
    execl("a", pclose(p));
}

Tested only with (and perhaps only works with) GCC.

Corresponding encoder program (manually remove the first character from its output):

#include <stdio.h>

int main()
{
    int c;
    while ((c = getchar()) != EOF) {
        while (c--) putchar(9);
        putchar(32);
    }
    return 0;
}

PleaseStand

Posted 2011-09-01T18:01:31.867

Reputation: 5 369

2

Yabasic (88 characters)

a$ = "<code here>"
for a = 1 to len(a$)
    if mid$(a$, a) < " " then b = b + 1
    else b$ = b$ + chr$(b) : b = 0
    endif
next
compile(b$)
a()

Use the same encoder program as for my C solution, but do not remove the first character. Your original code must be in the form of a subroutine a(), for example:

sub a():?"hello, world":end sub

PleaseStand

Posted 2011-09-01T18:01:31.867

Reputation: 5 369

1

D (101 chars)

import std.algorithm;mixin((){char[]r;foreach(c;splitter("<lots of whitspace>"," "))r~=cast(char)c.length;return r;}());

same encoding as in the question (no need for the newline)

ratchet freak

Posted 2011-09-01T18:01:31.867

Reputation: 1 334

2The point of this is that whitespace is free. I count 98 characters. Feel free to write readable code! – boothby – 2011-09-16T16:25:07.853

1

Bash (builtins only, 44 characters)

IFS=
eval `while read a
do printf '\'${#a}
done<<a
<code here>
a`

Corresponding encoder script:

od -b | cut -b9- | tr ' ' '\n' | while read a
do
    for (( b = 0; b < $((10#$a)); ++b ))
    do
        echo -n ' '
    done
    echo
done

PleaseStand

Posted 2011-09-01T18:01:31.867

Reputation: 5 369

Very nice. I consider myself a bit of a Bash hacker, and I had to man up a bit to grok this. – boothby – 2011-09-07T17:55:35.027

1

K5, 12 bytes

.`c$-':&9=" "

Execute (.) the string formed from the ascii values (`c$) given by the difference between each pair (-':) of the indices where (&) the input is a tab (9=" ").

Input is a string of tab- and non-tab characters, and the character values are encoded in the number of non-tabs (spaces or newlines) between each tab. An example encoder:

" ",/{(x#" "),"\t"}'-1+

Perform a running join beginning with a space over (" ",/) x spaces (x#" ") joined with a tab (,"\t") where X is each of ({...}') one minus the character values of the input string (-1+).

In action:

  enc: " ",/{(x#" "),"\t"}'-1+
  dec: .`c$-':&9=

  enc "2+3"
"                                                  \t                                          \t                                                  \t"
  dec enc "2+3"
5

JohnE

Posted 2011-09-01T18:01:31.867

Reputation: 4 632

0

Ruby, 43

Very straightforward, encoding is putting x spaces per line, where x is the ascii value of the char, decoding is reverse.

The following script is just a unary to ASCII converter and works even when things other than spaces are free:

eval("".split("\n").map{|x|x.length.chr}.join)

Just replace the empty string with the program that pleases you.

The thing in a more reusable format:

from_space = lambda {|text| text.split("\n").map{|x| x.length.chr}.join}
to_space = lambda {|text| text.chars.map{|x| " " * x.ord}.join("\n")}

p from_space [ to_space [ "abc" ] ] #=> "abc"

Caridorc

Posted 2011-09-01T18:01:31.867

Reputation: 2 254