Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

share|improve this question
    
If I call the transformed program P* with a new text, does P** contain both texts or only the last one? –  Tal Jun 15 at 13:41
    
So I am given the programs code as input when encoding and decoding? –  Martin Büttner Jun 15 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 at 13:54
2  
@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 Büttner Jun 15 at 14:07
4  
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 at 23:13

5 Answers 5

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.

share|improve this answer
    
+1 for the equivalent of "because I can" –  Jwosty Jun 16 at 4:51
    
How about healthy competition and single expression? –  Sieg Jun 16 at 6:57
    
That's a pretty large value of one you've got there. –  Gilles Jun 16 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)
share|improve this answer

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))
share|improve this answer

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
share|improve this answer

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\tmessage = \'\'')
        temp.add('\t\tfor i in .message, message += Convert.toString(i to char)')
        temp.add('\t\tFile.writeAllText(\'message.txt\', message)')
        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

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.