Convert a program to a palindromic program

15

1

A palindrome is a string that is the same forwards and backwards, such as "racecar".

Write a program in some language L, that takes any program P1 in language L as input, and outputs a palindromic program P2 in language L that does the same thing as P1.

You do not need to worry about handling input programs with syntax errors.

This is code golf, so the solution with the fewest number of bytes wins.

Peter Olson

Posted 2014-06-10T02:26:01.437

Reputation: 7 412

Can we define the language L? – Greg Hewgill – 2014-06-10T03:13:37.080

1@GregHewgill Yes. L is the language you choose to write your program in. – Justin – 2014-06-10T03:14:07.133

In some languages, this is surprisingly tough. – Justin – 2014-06-10T04:33:57.017

3With a turing complete subset of Python, this is a valid entry: x=input();print(x+'#'+x[::-1]). The subset is the set of all programs that don't include newlines. – Justin – 2014-06-10T04:58:22.667

Answers

17

Perl, 55 54 bytes

undef$/;$a=<>."\n__END__\n";print$a,scalar reverse$a;

Reads program source from stdin and writes to stdout.

Result of running on itself:

undef$/;$a=<>."\n__END__\n";print$a,scalar reverse$a;

__END__

__DNE__

;a$esrever ralacs,a$tnirp;"n\__DNE__n\".><=a$;/$fednu

Greg Hewgill

Posted 2014-06-10T02:26:01.437

Reputation: 2 641

+1 for not using comments – None – 2014-06-10T15:33:24.257

3I like that it marks the apparent gibberish at the bottom with "DNE" - a common shorthand for "Do Not Erase" used to mark things on chalkboards/whiteboards so that people don't mistake them for unimportant scribblings and wipe them off. – anaximander – 2014-06-10T15:55:33.533

how does it work, I don't know perl, more specifically how does it quine(get the line that it's reversing)? – Cruncher – 2014-06-10T20:05:59.937

@Cruncher: __END__ indicates the end of the parseable portion of the script. See http://perldoc.perl.org/functions/__END__.html For input, <> reads the input from stdin.

– Greg Hewgill – 2014-06-10T20:07:20.587

@GregHewgill the program source is read through stdin? That's odd. I assume that nothing after END goes through this stream then? – Cruncher – 2014-06-10T20:11:36.733

@Cruncher: The program doesn't read its own source. The program takes whatever input you give to it. You can give it itself as input, which is what I did for the example. – Greg Hewgill – 2014-06-10T20:13:42.550

@GregHewgill I misunderstood the question a bit. I got it now. I thought it was supposed to palindromize itself – Cruncher – 2014-06-10T20:19:58.527

21+ Works in most cases except when program ends with __DATA__ that is read.. eg. print while(<DATA>);\n__DATA__ will change behaviour. – Sylwester – 2014-06-11T09:51:53.497

1@Sylwester: True. This works for the subset of Perl scripts that don't use __DATA__. :) – Greg Hewgill – 2014-06-11T17:50:25.860

11

Java, 225 bytes

class c{public static void main(String[]a){String s="";java.util.Scanner r=new java.util.Scanner(System.in);while(r.hasNext())s+=r.nextLine()+"\n";s=s.replace("\n","//\n");System.out.print(s+new StringBuilder(s).reverse());}}

Output on itself (when prettified beforehand):

class c {//
    public static void main(String[] a) {//
        String s = "";//
        java.util.Scanner r = new java.util.Scanner(System.in);//
        while (r.hasNext()) s += r.nextLine() + "\n";//
        s = s.replace("\n", "//\n");//
        System.out.print(s + new StringBuilder(s).reverse());//
    }//
}//

//}
//}
//;))(esrever.)s(redliuBgnirtS wen + s(tnirp.tuo.metsyS        
//;)"n\//" ,"n\"(ecalper.s = s        
//;"n\" + )(eniLtxen.r =+ s ))(txeNsah.r( elihw        
//;)ni.metsyS(rennacS.litu.avaj wen = r rennacS.litu.avaj        
//;"" = s gnirtS        
//{ )a ][gnirtS(niam diov citats cilbup    
//{ c ssalc

Justin

Posted 2014-06-10T02:26:01.437

Reputation: 19 757

1

Problem if comment ending in *. See comment

– edc65 – 2014-06-17T22:08:20.510

10

Python 2, 68 bytes

import sys
x=''.join(l[:-1]+'#\n'for l in sys.stdin)
print x+x[::-1]

Doesn't work if run from IDLE, because you need to generate an EOF character to stop the program from waiting on input.

Output when run on itself:

import sys#
x=''.join(l[:-1]+'#\n'for l in sys.stdin)#
print(x+x[::-1])#

#)]1-::[x+x(tnirp
#)nidts.sys ni l rof'n\#'+]1-:[l(nioj.''=x
#sys tropmi

Thanks to Greg Hewgill for helping to hammer out problems and to golf.

Justin

Posted 2014-06-10T02:26:01.437

Reputation: 19 757

Nice job, beats my kinda lame Python attempt. – Greg Hewgill – 2014-06-10T04:00:14.010

1@GregHewgill I prefer a nice upvote to a nice comment ;-) – Justin – 2014-06-10T04:06:52.207

1Ok okay... I don't usually vote against myself. :) – Greg Hewgill – 2014-06-10T04:07:22.500

5@GregHewgill I vote "against" myself a lot. I upvote answers based on their merits, not based on whether or not I answered. – Justin – 2014-06-10T04:08:52.750

8

GolfScript, 10 9 bytes

"
}"+.-1%

Quite similar to minitech's solution, but it works well with newlines. It relies on GolfScript's funny (and undocumented) behavior to ignore an unmatched (and uncommented) }, as well as everything that follows it.

It will fail if the input contains an unmatched {, but that would technically constitute a syntax error.

How it works

"
}"   # Push the string "\n}".
+    # Concatenate it with the input string.
.    # Duplicate the modified string.
-1%  # Reverse the copy.

Example

$ echo -n '1{"race{car"}
> {"foo\"bar"}
> if#' | golfscript make-palindrome.gs
1{"race{car"}
{"foo\"bar"}
if#
}}
#fi
}"rab"\oof"{
}"rac{ecar"{1
$ echo '1{"race{car"}
> {"foo\"bar"}
> if#
> }}
> #fi
> }"rab"\oof"{
> }"rac{ecar"{1' | golfscript
race{car

Dennis

Posted 2014-06-10T02:26:01.437

Reputation: 196 637

Try 1\n2# (\n would be an actual newline character) as your input. – Justin – 2014-06-10T05:57:41.607

1@Quincunx: Pesky comments... A newline before the curly bracket should fix that. – Dennis – 2014-06-10T06:00:48.750

Before and after. Need to remain a palindrome. – Justin – 2014-06-10T06:06:04.800

@Quincunx: Of course. It should work now. – Dennis – 2014-06-10T06:09:08.923

5

x86 machine code on DOS (.com file) - 70 bytes

Dealing with .COM files, creating a palyndrome is easy - since the COM "loader" just puts the content of the file at address 100h and jumps there, the program must already hardcode its end somehow and ignore everything after it, so we can just append the reverse of the first N-1 bytes (only caveat: if the program somehow tries to do tricks with the length of file everything breaks).

Here is the hex dump of my .COM-palyndromizing .COM:

00000000  31 db 8a 1e 80 00 c6 87  81 00 00 ba 82 00 b8 00  |1...............|
00000010  3d cd 21 72 30 89 c6 bf  ff ff b9 01 00 ba fe 00  |=.!r0...........|
00000020  89 f3 b4 3f cd 21 3c 01  75 18 b4 40 bb 01 00 cd  |...?.!<.u..@....|
00000030  21 85 ff 75 e5 89 f3 f7  d9 88 ee b8 01 42 cd 21  |!..u.........B.!|
00000040  eb d8 47 74 f0 c3                                 |..Gt..|

It takes the input file on the command line, and writes the output on stdout; the expected usage is something like compalyn source.com > out.com.

Commented assembly:

    org 100h

section .text

start:
    ; NUL-terminate the command line
    xor bx,bx
    mov bl, byte[80h]
    mov byte[81h+bx],0
    ; open the input file
    mov dx,82h
    mov ax,3d00h
    int 21h
    ; in case of error (missing file, etc.) quit
    jc end
    ; si: source file handle
    mov si,ax
    ; di: iteration flag
    ; -1 => straight pass, 0 reverse pass
    mov di,-1
loop:
    ; we read one byte at time at a bizarre memory
    ; location (so that dl is already at -2 later - we shave one byte)
    mov cx,1
    mov dx,0feh
    mov bx,si
    mov ah,3fh
    int 21h
    ; if we didn't read 1 byte it means we either got to EOF
    ; or sought before the start of file
    cmp al,1
    jne out
    ; write the byte on stdout
    mov ah,40h
    mov bx,1
    int 21h
    ; if we are at the first pass we go on normally
    test di,di
    jnz loop
back:
    ; otherwise, we have to seek back
    mov bx,si
    ; one byte shorter than mov cx,-1
    neg cx
    ; dl is already at -2, fix dh so cx:dx = -2
    mov dh,ch
    mov ax,4201h
    int 21h
    jmp loop
out:
    ; next iteration
    inc di
    ; if it's not zero we already did the reverse pass
    jz back
end:
    ret

Tested on itself and the solutions to a previous question seems to work fine in DosBox, some more extensive testing on "canonical" DOS executables will follow.

Matteo Italia

Posted 2014-06-10T02:26:01.437

Reputation: 3 669

3

GolfScript, 8

.-1%'#'\

Doesn’t handle newlines, but nobody uses those in GolfScript.

Ry-

Posted 2014-06-10T02:26:01.437

Reputation: 5 283

6Using newline in string literals can be used quite often ;-) – Howard – 2014-06-10T05:10:02.590

2

Bash+coreutils, 39 bytes

f="`cat`
exit"
echo "$f"
tac<<<"$f"|rev

Reads from STDIN and outputs to STDOUT:

$ cat hello.sh 
#!/bin/bash

echo 'Hello, World!'

$ ./palin.sh < hello.sh 
#!/bin/bash

echo 'Hello, World!'
exit
tixe
'!dlroW ,olleH' ohce

hsab/nib/!#
$ 

Digital Trauma

Posted 2014-06-10T02:26:01.437

Reputation: 64 644

@user23013 Seems to work fine. At least a simple test like ( echo 'Hello, World!' ). bash pretty much ignores everything after the exit. – Digital Trauma – 2014-06-17T20:05:34.423

2

Javascript (ES6) Multi-line - 71

Kinda sorta stole Quincunx's comment method here:

alert((x=prompt().replace(/\n/g,'//\n')+'/')+[...x].reverse().join(''))

Single line - 49

alert((x=prompt()+'/')+[...x].reverse().join(''))

nderscore

Posted 2014-06-10T02:26:01.437

Reputation: 4 912

2

C++, 214 209 bytes

#include<cstdio>
#include<stack>
int main(){std::stack<char>s;int c;while((c=getc(stdin))>EOF){if(c=='\n')for(int i=2;i;i--)s.push(putchar('/'));s.push(putchar(c));}while(s.size()){putchar(s.top());s.pop();}}

Result of running on itself:

#include<cstdio>//
#include<stack>//
int main(){std::stack<char>s;int c;while((c=getc(stdin))>EOF){if(c=='\n')for(int i=2;i;i--)s.push(putchar('/'));s.push(putchar(c));}while(s.size()){putchar(s.top());s.pop();}}//

//}};)(pop.s;))(pot.s(rahctup{))(ezis.s(elihw};))c(rahctup(hsup.s;))'/'(rahctup(hsup.s)--i;i;2=i tni(rof)'n\'==c(fi{)FOE>))nidts(cteg=c((elihw;c tni;s>rahc<kcats::dts{)(niam tni
//>kcats<edulcni#
//>oidtsc<edulcni#

Greg Hewgill

Posted 2014-06-10T02:26:01.437

Reputation: 2 641

Fail when continuation char '' is used. Try [http://ideone.com/TCZHr9] – edc65 – 2014-06-11T07:42:22.630

@edc65: Yeah, I thought about that later. The only obvious way I can think of to handle that would be to unfold the folded lines first. – Greg Hewgill – 2014-06-11T08:30:37.107

can be done at small cost - se my C answer – edc65 – 2014-06-11T08:53:03.440

2

C 168 175

Correctly handles escaped newline inside source code

Edit 1 fixed bug when last newline missing
Edit 2 fixed bug when line inside comment ends with *: add a tab char before the // comment
(and golfed more)

b[999999];main(c,z){char*p,for(p=b;(*p=c=getchar())>=0;z=c,p++)c-10||(z-92?*p++=9,*p++=47,*p++=47,*p=c:(p-=2));*p=47;for(p=b;*p;)putchar(*p++);for(;p>b;)putchar(*--p);}

C99 Standard, valid code, many warnings

Ungolfed

b[999999]; // working buffer ~ 4M on 32 bit machine, max source size
// c is current char, z is previous char,
main(c,z) // z  start as argv pointer, will be out of char range
{
  char *p;
  for(p = b; 
      (*p=c=getchar()) >= 0; // while testing EOF copy char to buffer set c variable
      z=c, p++) // at end loop increment p and set previous = current
  {
      c-'\n' || // if newline 
       (z - '\\' // check if escaped
          ? *p++='\t',*p++='/',*p++='/', *p=c // if not escaped, add tab,/,/ and newline
          : (p-=2) // if escaped, drop both escape and newline
       ); 
  }
  *p='/'; // if last newline missing, will add a comment anyway
  for(p=b;*p;) putchar(*p++); // ouput buffer 
  for(;--p>=b;) putchar(*p); // outbut buffer reversed
}

edc65

Posted 2014-06-10T02:26:01.437

Reputation: 31 086

1there is a little bug in it. try /* *<NL> */int main(){} – jimmy23013 – 2014-06-17T19:38:26.243

2

Brainfuck, 749 without whitespace (not golfed)

This produces brainfuck programs which mirrored palindromes, i.e. they are are mirror images of themselves.

++++++++++
[->++++>+++++++++<<]>+++.>+..<.>++.
>>>>+[>,]<-[+<-]
>[
  [-<+<<+>>>]
  +<-------------------------------------------[-<+>>[-]<]>[-<<<.>>>]
  +<<-[->+>[-]<<]>>[-<<<.>>>]
  +<-[-<+>>[-]<]>[-<<<.>>>]
  +<<-[->+>[-]<<]>>[-<<<.>>>]
  +<--------------[-<+>>[-]<]>[-<<<.>>>]
  +<<--[->+>[-]<<]>>[-<<<.>>>]
  +<-----------------------------[-<+>>[-]<]>[-<<<.>>>]
  +<<--[->+>[-]<<]>>[-<<<.>>>]
  <[-]>>
]
<<<<[<]
<--.<.>++..--..<.>++.
>>[>]
<[
  [->+>>+<<<]
  +>-------------------------------------------[->+<<[-]>]<[->>>.<<<]
  +>>-[-<+<[-]>>]<<[->>>.<<<]
  +>-[->+<<[-]>]<[->>>.<<<]
  +>>-[-<+<[-]>>]<<[->>>.<<<]
  +>--------------[->+<<[-]>]<[->>>++.--<<<]
  +>>--[-<+<[-]>>]<<[->>>--.++<<<]
  +>-----------------------------[->+<<[-]>]<[->>>++.--<<<]
  +>>--[-<+<[-]>>]<<[->>>--.++<<<]
  >[-]<<
]
<--.<.>++..<.

Given a program it outputs

+[[+]PROGRAM[+]][[+]MIRROR[+]]+

with PROGRAM and MIRROR replaced by the program (without non-brainfuck characters) and its mirror image.

cardboard_box

Posted 2014-06-10T02:26:01.437

Reputation: 5 150

1

C# - 174

using System;using System.Linq;class c{public static void Main(){var a="";var b="";while((a=Console.ReadLine())!="")b+=a+"//\n";Console.Write(b+string.Concat(b.Reverse()));}}

Test Input:

using System; 
using System.Linq; 
class c 
{ 
    public static void Main() 
    { 
        var a = ""; 
        var b = ""; 
        while ((a = Console.ReadLine()) != "") 
            b += a + "//\n"; 
        Console.Write(b+string.Concat(b.Reverse())); 
    } 
} 

Test Output:

using System; 
using System.Linq; 
class c 
{ 
    public static void Main() 
    { 
        var a = ""; 
        var b = ""; 
        while ((a = Console.ReadLine()) != "") 
            b += a + "//\n"; 
        Console.Write(b+string.Concat(b.Reverse())); 
    } 
} 

// }
// }
// ;)))(esreveR.b(tacnoC.gnirts+b(etirW.elosnoC
// ;"n\//" + a =+ b
// )"" =! ))(eniLdaeR.elosnoC = a(( elihw
// ;"" = b rav
// ;"" = a rav
// {
// )(niaM diov citats cilbup
// {
// c ssalc
// ;qniL.metsyS gnisu
// ;metsyS gnisu

jzm

Posted 2014-06-10T02:26:01.437

Reputation: 369

I think you may have misunderstood one of the instructions. Your program should be able to take any program as input, and write out a palindromic program that does the same thing as the original program. – Greg Hewgill – 2014-06-11T02:20:02.757

It can.. If I input the C++ code from your answer, it returns exactly what you have. – jzm – 2014-06-11T02:24:57.823

All your program does is reverse its input. The output of your program is not a complete palindromic program. – Greg Hewgill – 2014-06-11T02:30:08.573

Oh yeah, i get ya. Updated - better now? – jzm – 2014-06-11T02:36:49.520

Well, almost. Now it works for your program (with the // at the end of each line), but would not work for any other program. It's a very simple change to make it work from this point, though. – Greg Hewgill – 2014-06-11T02:39:31.367

Ahh yes. added it. //\n – jzm – 2014-06-11T02:41:35.260

2Yup, that's it. Your test output should have the // at the end of each line now though. – Greg Hewgill – 2014-06-11T02:42:59.567

0

PHP, 96 bytes

function a($b){
    echo $c = "a('$b')" . strrev("a)'" . $b . "'(");
    $d = substr($c, 0, strlen($b) + 5);
    eval("$d;");
}

Sample Usage:

a('apple'); // echoes a('apple')('elppa')a until your bytes get exhausted

This is nothing clever. It's just a simple piece of code that does the job... I was in a mood for playing. I do know that this code is rife with bad programming practices!

Finally, I will gladly accept any criticism and edits to this code!

TribalChief

Posted 2014-06-10T02:26:01.437

Reputation: 111

Welcome to Code Golf. This is a function, not a program. See the other answers, they provide good examples. – A.L – 2014-06-10T09:21:26.873

0

Cobra - 134

class P
    def main
        i=List<of String?>(Console.readLine.split('\n'))
        print '/#\n[i.reversed.join("\n")]\n#/#\n[i.join("\n")]\n#/'

Οurous

Posted 2014-06-10T02:26:01.437

Reputation: 7 916

0

Racket 133

(require srfi/13)(let((r read-line)(w display))(let l((i(r)))(when
(not(eq? eof i))(w i)(w";\n")(l(r))(w"\n;")(w(string-reverse i)))))

Ungolfed (but still very imperative):

(require srfi/13)
(let recurse ((instr (read-line)))
  (when (not (eof-object? instr))
    (display instr)
    (display ";\n")
    (recurse (read-line))
    (display "\n;")
    (display (string-reverse instr))))

Output when given the ungolfed version as input:

(require srfi/13);
(let recurse ((instr (read-line)));
  (when (not(eof-object? instr));
    (display instr);
    (display ";\n");
    (recurse (read-line));
    (display "\n;");
    (display (string-reverse instr))));

;))))rtsni esrever-gnirts( yalpsid(    
;)";n\" yalpsid(    
;))enil-daer( esrucer(    
;)"n\;" yalpsid(    
;)rtsni yalpsid(    
;))rtsni ?tcejbo-foe(ton( nehw(  
;)))enil-daer( rtsni(( esrucer tel(
;)31/ifrs eriuqer(

Sylwester

Posted 2014-06-10T02:26:01.437

Reputation: 3 678