# Exploit “free whitespace”

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.

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

• Since whitespace at the beginning of a program is always non-functional, .n/{,}%+~ would work as well. – Dennis Oct 8 '15 at 15:56

## CPAN, 16

use Acme::Bleach;


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

• I call cheat on this, that is a complete set of operators that is nothing but whitespace – ratchet freak Sep 1 '11 at 19:34
• This is not a cheat. It's cheap, but acceptable. – boothby Sep 1 '11 at 21:59
• This 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 Sep 5 '11 at 22:30
• @trinithis: as do none of the other programs presented here. Why pick specifically on this one? – J B Sep 6 '11 at 7:39
• I noticed it and it stands out as a what does this do, it only looks like it imports. – Thomas Eding Sep 6 '11 at 15:37

## 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 • you can put tabs in with \t and we'll believe it works with whitespace... – boothby Sep 5 '11 at 7:14 • @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 Sep 5 '11 at 9:04 ## 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);  • Replace (s)=>... in the arrow function to s=>... to save two bytes – andrewarchi Jun 15 '17 at 5:06 • Keep spaces between any two char and at worst use jsfuck to make it work(and better use " t " [ 1 ] to mean "t") – l4m2 Dec 11 '18 at 11:40 • 44B eval("".replace(/ +/g,s=>' []+!()'[s.length])) – l4m2 Dec 11 '18 at 11:42 ## 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  ## 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; }  ## 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) • The point of this is that whitespace is free. I count 98 characters. Feel free to write readable code! – boothby Sep 16 '11 at 16:25 ## 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

• Very nice. I consider myself a bit of a Bash hacker, and I had to man up a bit to grok this. – boothby Sep 7 '11 at 17:55

# 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


# 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"
`