Program, który koduje wiadomość we własnym tekście

13

Napisz program, który koduje dany tekst we własnym tekście, podanym jako dane wejściowe, bez zakłócania jego logiki. Program musi również działać jako dekoder, przywracając oryginalną wiadomość z jej tekstu. Po transformacji musi zachować swoje funkcje kodowania / dekodowania.

Mówiąc bardziej formalnie, wymagany program P musi wykonać następujące przekształcenia z podanym tekstem komunikatu M:
P (M, P) -> P *
P * (P *) -> M

Tutaj P * jest przekształconym programem, który również musi spełniać powyższe reguły, to znaczy:
P * (M2, P *) -> P **
P ** (P **) -> M2
i tak dalej ... Każdy kolejne kodowanie nie usuwa wcześniej zakodowanego tekstu, więc P ** przenosi dwie wiadomości - M i M2.

Najłatwiejszym sposobem na rozróżnienie między trybami kodowania / dekodowania jest obecność dodatkowego argumentu M, ale ostateczna decyzja należy do Ciebie, pod warunkiem, że jest to wyraźnie określone. Program może odczytać własny tekst z pliku. Jeśli wybrany język nie ma na to środków, tekst źródłowy można przekazać do programu w jakikolwiek inny sposób.

Istnieją oczywiście trywialne rozwiązania, więc jest to raczej konkurs popularności. Niemniej jednak nakładam ograniczenie zabraniające komentowania w tekście programu.

Tr00rle
źródło
Jeśli wywołam przekształcony program P * z nowym tekstem, czy P ** zawiera oba teksty, czy tylko ostatni?
Tal
Czy dostaję kod programu jako dane wejściowe podczas kodowania i dekodowania?
Martin Ender
W jaki sposób program ma rozróżniać między proszeniem o dekodowanie zakodowanej wiadomości a proszeniem o zakodowanie wiadomości, która po prostu sama jest zakodowaną wiadomością?
celtschk
2
@celtschk sądząc po notacji OP: jeśli twój program ma dwa wejścia, zakoduj pierwsze wejście na drugim wejściu. jeśli program ma tylko jedno wejście, wyodrębnij łańcuch ostatnio zakodowany w tym wejściu.
Martin Ender
4
Czy powinien istnieć sposób na odzyskanie P * z P **? Jeśli nie, to po co wymagać, aby „ P ** przenosi dwie wiadomości - M i M2 ”? Przykro mi, ale chociaż to wyzwanie wydaje się interesujące, specyfikacja jest dla mnie zbyt myląca.
Ilmari Karonen

Odpowiedzi:

8

Perl

Jest to jedna linijka w Perlu tylko dlatego, że jest to możliwe.

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

Wiadomości są pisane później __DATA__, od najnowszych.

Greg Hewgill
źródło
Co powiesz na zdrową konkurencję i ekspresję?
patrz
To dość duża wartość tego, co tam masz.
Gilles „SO- przestań być zły”
4

Pyton

Wiesz co? Dlaczego nie zrobić z tego pojedynczego wyrażenia?

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)

Stara wiadomość; Funkcja P przyjmuje podane argumenty i wyświetla wynikowy kod / zdekodowany tekst.

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)
patrz
źródło
2

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") + ")");
    }
}

Nie jestem pewien, czy poprawnie rozumiem instrukcję problemu: mój dekoder dekoduje dowolny program i zwraca najnowszą wiadomość zakodowaną w danym programie.

Kod testowy:

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))
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
źródło
2

Partia

@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

Uwaga: po „ostatnim wierszu” musi znajdować się znak powrotu karetki goto :EOF.

To wymaga dwóch danych wejściowych ze standardowego wejścia. Pierwszym z nich jest to, co chcesz zrobić; e, lub d(kodowanie i dekodowanie). Drugie wejście zależy od pierwszego - jeśli pierwsze wejście e, to drugie wejście będzie wiadomością, którą chcesz zakodować - jeśli tak d, to drugie wejście będzie numerem wiadomości, którą chcesz zdekodować (która będzie być dostarczone po zakodowaniu wiadomości).

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

H:\uprof>ed.bat d 1
Just a message
nieszczęście
źródło
0

Kobra

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)

Chociaż pomysł jest trywialny, wykonanie tego pomysłu jest mniej ważne.

Kodowanie

Kodowanie wiadomości w programie doda wiersz .message = .message ? xnatychmiast po def main. Ta linia sprawdza, czy .messagejest zero, a jeśli tak, to ustawia .messagetablicę liczb całkowitych zawierającą wartości kodów znaków każdego znaku w komunikacie; funkcja zerowania i pozycjonowania pozwala uniknąć zastąpienia nowej wiadomości starszą. Nowy program zostanie zapisany wencode.cobra

Rozszyfrowanie

Dekodowanie programu doda trzy linie na końcu głównej metody, co spowoduje, że program przekonwertuje kody char .messagena ciąg znaków, który zostanie następnie zapisany message.txtpo uruchomieniu nowego programu. Nowy program jest następnie zapisywany decode.cobrai wywoływany na nim kompilator.

decode.cobra jest używany jako plik tymczasowy i nie może być używany do kodowania lub dekodowania innej wiadomości, użyj oryginału lub encode.cobra

Obrzydliwe
źródło