# Program that encodes a message into its own text

Write a program that encodes given text into its own text, provided as input, without disrupting its logic. The program must also work as a decoder, restoring the original message from its text. It must retain its encoding/decoding functions after transformation.

More formally speaking, the required program P must perform the following transformations with the given message text M:
P(M,P)->P*
P*(P*)->M

Here P* is the transformed program, which also must satisfy the above rules, that is:
P*(M2,P*)->P**
P**(P**)->M2
and so on... Each subsequent encoding doesn't erase previously encoded text, so P** carries two messages - M and M2.

The easiest way for the program to distinguish between encoding/decoding modes is by the presence of the extra argument M, but the final decision is up to you, provided it is clearly stated. The program may read it's own text from the file. If the chosen language doesn't have means for this, the source text can be passed to the program in any other way.

There are trivial solutions, of course, so this is rather a popularity contest. Nevertheless, I impose restriction forbidding comments in the program text.

• If I call the transformed program P* with a new text, does P** contain both texts or only the last one? – Tal Jun 15 '14 at 13:41
• So I am given the programs code as input when encoding and decoding? – Martin Ender Jun 15 '14 at 13:48
• How is the program intended to distinguish between being asked to decode an encoded message, and being asked to encode a message which just happens to be itself an encoded message? – celtschk Jun 15 '14 at 13:54
• @celtschk judging by the OPs notation: if your program is given two inputs, encode the first input in the second input. if the program is given only one input, extract the string most recently encoded in that input. – Martin Ender Jun 15 '14 at 14:07
• Is there supposed to be any way to recover P* from P**? If not, why require that "P** carries two messages - M and M2"? I'm sorry, but although this challenge seems interesting, the spec is just way too confusing for me. – Ilmari Karonen Jun 15 '14 at 23:13

# Perl

This is a one-liner in Perl just because it's possible.

if($ARGV[0]){open(F,__FILE__);while(<F>){print;print"$ARGV[0]\n"if/^_/;}}else{print<DATA>;}
__DATA__


The messages are written after __DATA__, most recent first.

• How about healthy competition and single expression? – seequ Jun 16 '14 at 6:57
• That's a pretty large value of one you've got there. – Gilles 'SO- stop being evil' Jun 16 '14 at 11:46

# Python

You know what? Why not make it a single expression?

P = (lambda M,P=None:(lambda t:P[:74]+repr(M)[1:-1]+"'))"if P else M[74:-3])(''))
Pc = "(lambda M,P=None:(lambda t:P[:74]+repr(M)[1:-1]+\"'))\"if P else M[74:-3])(''))"
P2c = P('Hi there, mate!', Pc)
print "Encode tests:"
print " P2 = P('Hi there, mate!', Pc) =", P2c
exec 'P2 = ' + P2c
print " P2(\"Test 2's the best.\", P2c) =", P2("Test 2's the best.", P2c)

print "Decode tests:"
print "P2(P2) =", P2(P2c)
print "P(P2)  =", P(P2c)
print "P2(P)  =", P2(Pc)
print "P(P)   =", P(Pc)


Old message; The function P takes the arguments as specified and outputs the resulting code / decoded text.

def P(data,func=None):
text = ""
if func:
return func[:35]+data+'"\n'+'\n'.join(func.split('\n')[2:])
return data[35:].split('\n')[0][:-1]

# The source code.
Pc = """def P(data,func=None):
text = ""
if func:
return func[:35]+data+'"\\n'+'\\n'.join(func.split('\\n')[2:])
return data[35:].split('\\n')[0][:-1]"""

P2c = P('Hi there, mate!', Pc)
print "Encode test:"
print "P('Hi there, mate!', P) ->"
print P2c

# This is outputted by P('Hi there, mate!', code-of-P)
def P2(data,func=None):
text = "Hi there, mate!"
if func:
return func[:35]+data+'"\n'+'\n'.join(func.split('\n')[2:])
return data[35:].split('\n')[0][:-1]

print "P2('Text 2', P2) -<"
print P2('Text 2', P2c)

print "Decode test:"
print "P2(P2) =", P2(P2c)
print "P(P2)  =", P(P2c)
print "P2(P)  =", P2(Pc)
print "P(P)   =", P(Pc)


## JavaScript

var transform = function (p, m) {
var _M_ = '';
var source = arguments.callee.toString();
var msgre = /(_M_ = ').*(';)/;
var regex = new RegExp(source.replace(/[.*+?^${}()\\|]/g, "\\$&").replace(msgre, "$1(.*)$2"));

var a = p.toString().match(regex);

if (!a) {
throw "first argument must be a transform function"
} else {
a = a[1];
}

if (typeof m == "undefined") {
return eval("[" + a.split("|")[0] + "]").map(x=>String.fromCharCode(x)).join("");
} else {
a = m.toString().split("").map(x => x.charCodeAt(0)) + (a.length ? "|" + a: a);
return eval("(" + source.replace(msgre, "$1" + a + "$2") + ")");
}
}


Not sure if I understand the problem statement correctly: my decoder will decode any program and return the latest message that is encoded in the given program.

Test code:

P1 = transform(transform, "first message");
P2 = P1(P1, "second message");

console.log(P1(P1));
console.log(P2(P2));

console.log(P2(P1));
console.log(P1(P2));

// Unspecified behavior
console.log(transform(transform))


## Batch

@echo off

setLocal enableDelayedExpansion
for /f %%a in (%0) do set a=%%a

if "%~1"=="e" (
set /a a+=1
echo !a! %~2 >> %0
echo message encoded as !a!
) else if "%~1"=="d" for /f "skip=12 tokens=1*" %%a in (%0) do if "%%a"=="%~2" echo %%b

goto :EOF


Note there needs to be a carriage return after 'the last line' of goto :EOF.

This takes two inputs from stdin. The first of which is what you want to do; e, or d (encode and decode). The second input depends on the first - if the first input is e, then the second input will be the message that you want to encode - if it is d, then the second input will be the number of the message you wish to decode (that will be provided after encoding a message).

H:\uprof>ed.bat e "Just a message"
message encoded as 1

H:\uprof>ed.bat d 1
Just a message


# Cobra

use System.Diagnostics
class Program
var message as int[]? = nil
def decode(program as String)
temp = List<of String>(program.split('\n'))
temp.insert(4, '\t\tEnvironment.exit(0)')
temp.add('\t\tfor i in .message, message += Convert.toString(i to char)')
program = temp.join('\n')
File.writeAllText('decode.cobra', program)
process = Process()
process.startInfo.fileName = 'cmd.exe'
process.startInfo.arguments = '/C cobra decode.cobra'
process.start
def encode(message as String, program as String)
temp = List<of String>()
for i in message.toCharArray, temp.add(Convert.toString(i to int))
message = '@' + Convert.toString(c'[')
for n in temp.count-1, message += temp[n] + ','
message += temp.pop + ']'
temp = List<of String>(program.split('\n'))
temp.insert(26,'\t\t.message = .message ? [message]')
program = temp.join('\n')
File.writeAllText('encode.cobra', program)
def main
#call methods here
#.encode(message, program)
#.decode(program)


While the idea is trivial, the execution of said idea is less-so.

## Encoding

Encoding a message in the program will add the line .message = .message ? x immediately after def main. This line checks if .message is nil, and if so, then it sets .message to an integer array containing the character code values of each character in the message; the nil-check and positioning avoid overwriting the new message with an older one. The new program is saved to encode.cobra

## Decoding

Decoding the program will add three lines at the end of the main method which cause the program to convert the char codes in .message to a string, which is then saved to message.txt when the new program is run. The new program is then saved to decode.cobra and the compiler is invoked on it.

decode.cobra is used like a temporary file and cannot be used to encode or decode another message, use the original or encode.cobra